2017-10-13 1 views
2

mit dem folgende Codebeispiel:JMM Garantien innerhalb einer Try-mit-Ressource-Neuordnungs & JNI rufen

try (AutoClosable closable = new XXX()) { 
     o.method1(closable); 
     o.method2(); 
} 

Ist das Java-Speichermodell HotSpot closable.close() vor o.method2() neu anordnen kann?

Ich verzichte absichtlich auf Implementierungsdetails wie schließt Methode1 verschließbar? im ersten Teil dieser Frage.


Mein spefic Anwendungsfall ist dies:

ich eine C-Bibliothek haben, die wie folgt zusammengefasst werden können:

static char* value; 

void capture(char* ptr){ 
     value = ptr; 
} 

int len(void) { 
    return strlen(value); 
} 

Diese native Bibliothek gewickelt JNA mit

interface CApi extends Library { 

static { 
    Native.register("test.so", CApi.class) 
} 

    void capture(Pointer s); 
    int test(); 
} 

Und mein ursprünglicher Clientcode sieht ungefähr so ​​aus:

Das Problem mit dieser ersten Version ist, dass m von Java zugewiesen wurde und der Lebenszyklus dieses Speichers an m gebunden ist, die stark erreichbar ist. m ist nicht stark mehr erreichbar einmal capture(m) und Speicher wird freigegeben werden, wenn GC Tritte in (JNA auf finalize setzen nativen Speicher frei)

Um dies zu verhindern, dass ich JNA die Unterklasse vorgeschlagen Memory ein AutoClosableMemory einzuführen. Die Idee ist, dass die Verwendung eines Try-with-Resource-Konstrukts klar aussagen würde, dass die Ressource in diesem Bereich stark erreichbar ist. Der Bonus, dass wir das native Gedächtnis befreien konnten, ist bald da wir es nicht mehr brauchen, anstatt auf einen GC warten zu müssen (hey das ist RAII!). Ich

try (AutoClosableMemory m = [...]) { 
    cApi.capture(m); 
    cApi.test(); 
} 

Am garantiert, dass m.close() nie vor cApi.test() geltend gemacht werden und dass m ist stark erreichbar? In diesem Fall wird m von der zugrunde liegenden C-API erfasst, aber der Java-Compiler hat keine Möglichkeit, sie zu kennen.

Antwort

4

Theoretisch könnte die JVM die Anweisungen neu anordnen, aber das Ergebnis der Methode muss korrekt bleiben. HotSpot versteht nativen Code nicht und um die Korrektheit zu garantieren, wird Code nie um native Anweisungen herum angeordnet.

+0

Ich war auf der Suche nach etwas wie "es re-Code nie um native Anweisungen" haben Sie einen Link dafür? – Oleg

+1

Native Codeblöcke werden als externe Aktionen in der JLS formalisiert. Sie implizieren eine Vorkommnis-Beziehung mit ihrem vorherigen und nachfolgenden Code. Ich gab einmal diese Präsentation, die Sie hilfreich finden könnten: https://youtu.be/XgiXKPEILoc Ich spreche über externe Maßnahmen in Minute 40. –

+1

Danke, ausgezeichnete Gespräche. Ich denke, du solltest es zu deiner Antwort hinzufügen. Über was Sie hier sprechen (https://youtu.be/XgiXKPEILoc?t=40m37s), wird die Frage von OP genau behandelt. – Oleg

1

Für einen Thread wird garantiert, dass alle in der gleichen Reihenfolge wie in Ihrem Code ausgeführt werden (jede Neuanordnung, die passiert, kann in keiner Weise Ihr Programm beeinträchtigen). Das Neuanordnen kann nur Auswirkungen darauf haben, wie andere Threads sehen, was passiert. In Ihrer Frage gibt es nur einen Thread, so dass Ihr Programm garantiert cApi.test() vor m.close() aufrufen kann.

+0

Das ist auch mein Verständnis. Allerdings wollte ich gerne verstehen, was den Compiler speziell daran hindert, den Abschluss neu zu ordnen. Aus Java-Sicht ist ihre Abhängigkeit zwischen den beiden Anweisungen nicht so, dass das Schließen nicht _as-if-serial_ bricht. –

+0

@ ClémentMATHIEU Nun, wenn es sich auf Ihr Programm auswirken wird, wird es * as-if-serial brechen. Ich werde versuchen, etwas Spezifischeres zu finden, aber es ist im Allgemeinen immer wahr. Hier geht es nicht um Java, sondern um die JVM und die CPU, von denen sie wissen, womit sie davonkommen können. – Oleg

Verwandte Themen