2010-12-02 9 views
10

Was ich meine ist, wenn ich ein globales Referenz-Projekt in C++ erstellen, und dann an einige Java-Code übergeben, und Löschen löschen DeleteGlobalRef(), ist das zugrunde liegende Java-Objekt möglicherweise Müll sofort gesammelt, so dass jede zukünftige Java Code, der bereits auf dieses Objekt verweist, könnte mit einer NullPointerException zurückkommen? Genauer gesagt, wenn ich einige C++ Code, der so etwas wie dieses vereinfachte Beispiel tut:Wenn JNI DeleteGlobalRef() aufgerufen wird, wird das entsprechende Java-Objekt Garbage Collected gesammelt?

static jobject myObjGlobalRef; 
static JNIEnv* env = /* call to create a JVM and get the JNI env */; 
jobject ReturnMyObj() 
{ 
    /* <<Code that defines class, constructorId, and param1 goes here>> */ 

    jobject localObj = env->NewObject(class, constructorId, param1); 
    myObjGlobalRef = env->NewGlobalRef(localObj); 
} 

void DeleteMyObj() 
{ 
    env->DeleteGlobalRef(myObjGlobalRef); 
} 

myObjGlobalRef = ReturnMyObj(); 

jobject otherExistingGlobalRef = /* Assume we get another global ref to another parent obj somewhere else */ 
/* ... other code here ... */ 
// Invoke some method on some other pre-existing global reference that uses 
// myObjGlobalRef, lets assume this method stores the object referenced by 
// myObjGlobalRef into a parent object referenced by otherExistingGlobalRef: 
env->CallVoidMethod(env, otherExistingGlobalRef, addASubObjectMethodId, myObjGlobalRef); 

DeleteMyObj(); 

// Does the pointed to by myObjGlobalRef still exist here, assuming that 
// otherExistingGlobalRef now references it? 

Wie funktioniert das in JNI? Ist eine "GlobalReference" für ein Objekt nur eine Referenzzählung für das Objekt, so dass wenn ich das GlobalReference-Projekt freigebe, es nicht unbedingt Garbage das zugrunde liegende Java-Objekt sammelt, bis alle Verweise darauf (z. B. das "Eltern" -Objekt andere ExistingGlobalRef Referenzierung es) sind weg?

Wenn Sie dies beantworten können und einen Link zu einigen offiziellen Java/Sun/Oracle-Dokumenten zur Verfügung stellen, die Ihre Antwort unterstützen, erhalten Sie ein Bonus-Lob :-).

+0

Sie möchten vielleicht https://developer.android.com/training/articles/perf-jni.html lesen? Sie erwähnen einige nützliche Tipps zu diesem Thema. –

Antwort

11

DeleteGlobalRef() befreit die Referenz, nicht das Objekt.

Wenn dies der letzte erreichbare Verweis war, dann ist das referenzierte Objekt für die Garbage Collection verfügbar.

Ist ein „GlobalReference“ auf ein Objekt nur einen Referenzzähler für das Objekt

Nein, es ist nur eine Referenz, die gültig bleibt, bis Sie es explizit freizugeben. Die Garbage-Collection von Java verlässt sich überhaupt nicht auf Referenzzählungen.

Siehe auch Oracle's documentation on global references.

+0

Das war meine Vorahnung, und ich habe diese bestimmte Oracle-Seite vorher gesehen, aber es gab mir keine warmen verschwommenen Bezugnahmen. Sie haben jedoch mein Gehirn geweckt, um zu suchen, und ich fand diesen Link: http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html über Java-Speicherbereinigung und Referenzen. Wenn wir annehmen können, dass eine globale JNI-Referenz genauso behandelt wird wie jede andere starke Java-Referenz, hilft mir das, sich besser über Ihre Antwort zu fühlen. –

+1

Ich war auf der Suche nach einer Einführung in Java GC für Sie, froh, dass Sie eine gefunden haben. Das Dokument für DeleteGlobalRef() sagt speziell "Löscht die globale * Referenz *, auf die von globalRef verwiesen wird". Meine Erfahrung ist, dass das genau ist; und wenn es nicht wäre, würden schlimme Dinge passieren. :) –

+0

Für zukünftige Referenz ist der sun.com Link in meinem Kommentar tot. Aber der Name des Papierbuchs mit einigen netten GC- und Referenzinformationen ist "Java ™ Platform Performance: Strategien und Taktiken" von S. Wilson und J. Kesselman, falls jemand Interesse daran hat, weitere Informationen zu diesem Thema zu finden. (Sie können möglicherweise eine elektronische Kopie online finden, wenn Sie genug herumgraben). –

Verwandte Themen