2010-12-02 12 views
10

Lo que quiero decir es que si creo un jobject de referencia global en C++, y luego transfiero eso a algún código Java, y elimino la llamada DeleteGlobalRef(), ese objeto java subyacente es posiblemente recolectado inmediatamente, de modo que cualquier Java futuro El código que ya se está refiriendo a ese objeto podría regresar con una NullPointerException? En concreto, si tengo algo de código C++ que hace algo como este ejemplo simplificado:Si se llama a JNI DeleteGlobalRef(), ¿el objeto java correspondiente obtiene basura recolectada?

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? 

¿Cómo funciona esto en la JNI? Es una "referencia global" en un objeto solo un recuento de referencia para el objeto, de modo que si libero el jobject de GlobalReference, no necesariamente recoge el objeto java subyacente hasta que todas las referencias al mismo (como el objeto "principal" otro referencia existente de ReListGlobal)) se han ido?

Si puede responder esto y proporcionar un enlace a alguna documentación oficial de Java/Sun/Oracle que respalde su respuesta, obtendrá un premio adicional :-).

+0

Es posible que desee leer https://developer.android.com/training/articles/perf-jni.html? Mencionan algunos consejos útiles sobre este tema. –

Respuesta

11

DeleteGlobalRef() libera la referencia , no es el objeto.

Si esa fue la última referencia accesible, el objeto al que se hace referencia está disponible para la recolección de elementos no utilizados.

es un "GlobalReference" en un objeto sólo un recuento de referencia al objeto

No. Es sólo una referencia que sigue siendo válida hasta que libere de forma explícita. La recolección de basura de Java no depende en absoluto de los recuentos de referencia.

Véase también Oracle's documentation on global references.

+0

Esta fue mi corazonada, y he visto esa página de Oracle en particular antes, pero no me dio una cálida confusa con respecto a las referencias. Sin embargo, despertaste mi cerebro para ir a buscar y encontré este enlace: http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html sobre la recolección de basura y las referencias de Java. Si podemos suponer que una referencia global JNI se trata igual que cualquier otra referencia Java (fuerte), eso me ayuda a sentirme mejor con respecto a su respuesta. –

+1

Estaba buscando una introducción a Java GC para ti, me alegra que hayas encontrado una. El documento para DeleteGlobalRef() dice específicamente "Elimina la referencia * global * apuntada por globalRef". Mi experiencia ha sido que esto es exacto; y si no fuera así, pasarían cosas malas. :) –

+0

Para referencia futura, el enlace de sun.com en mi comentario está muerto. Pero el nombre del libro en papel con una buena información sobre referencias y GC es "Rendimiento de la plataforma Java ™: estrategias y tácticas" de S. Wilson y J. Kesselman, si alguien está interesado en buscar más información sobre el tema. (Es posible que pueda encontrar una copia electrónica en línea si busca lo suficiente). –

Cuestiones relacionadas