java garbage-collection jvm jdi jdwp

java - Duración de espejos JDI de objetos que viven en una JVM remota



garbage-collection jdwp (2)

Aunque no puedo encontrar ninguna documentación que aborde las cosas exactamente desde el ángulo que quería, una combinación de ver el código fuente del paquete com.sun.tools.jdi en GrepCode y la especificación del protocolo JDWP en el sitio web de Oracle me lleva a la conclusión de que :

  1. Los valores primitivos "reflejados" nunca mueren dado que todo el valor primitivo vive en el cliente JDI hasta que necesita ser transmitido al servidor utilizando el protocolo JDWP. ( No habría una ventaja para mantener un control de un valor primitivo que existe solo en el servidor en cualquier caso, ya que se necesitarían tantos bytes como para enviar el control sobre el transporte, ya que enviaría simplemente el valor primitivo !
  2. Cualquier duplicado de un tipo de referencia, incluida una referencia a una String creada por VirtualMachine.mirrorOf(String) , puede recopilarse como basura en cualquier momento.

Como soporte para el n. ° 1, consulte, por ejemplo, la fuente de com.sun.tools.jdi.VirtualMachineImpl.mirrorOf(long) : solo instancia una nueva instancia de LongValueImpl y devuelve:

public LongValue mirrorOf(long value) { validateVM(); return new LongValueImpl(this,value); }

y se puede ver que ni el constructor de LongValueImpl , ni ninguno de los constructores de sus superclases hasta MirrorImpl hacen nada que transmita datos a través del transporte JDWP y así altere el estado de la JVM del servidor.

Contraste con el n. ° 2 El punto de partida en JDI JavaDoc es que cualquier objeto duplicado de ObjectReference podría ser basura recolectada en cualquier momento:

Cualquier método en ObjectReference o que directa o indirectamente tome ObjectReference como parámetro puede arrojar ObjectCollectedException si el objeto duplicado se ha recolectado como basura.

Esto es corroborado por la fuente de com.sun.tools.jdi.VirtualMachineImpl.mirrorOf(String) , habla con el agente de JDWP en el servidor. Esta es solo la confirmación de que, como cualquier ObjectReference una StringReference creada de esta manera es susceptible a GC en cualquier momento, incluido de inmediato ...

public StringReference mirrorOf(String value) { validateVM(); try { return (StringReference)JDWP.VirtualMachine.CreateString. process(vm, value).stringObject; } catch (JDWPException exc) { throw exc.toJDIException(); } }

Por lo que puedo decir, si tiene ObjectReference , debe proteger todos los intentos de interactuar con el objeto duplicado en la JVM remota en un bucle que atrapa ObjectCollectedException menos que todos los hilos en la JVM remota estén suspendidos. Por ejemplo, si tiene un método en su cliente JDI que crea una String en la JVM remota y devuelve una referencia que no es de recolección de basura, puede hacer algo en esta línea:

StringReference safeStringRef(VirtualMachine vm, String string) { ObjectCollectedException lastCause = null; for (int numTries = 0; numTries < SANE_TRY_LIMIT; ++numTries) { StringReference stringRef = vm.mirrorOf(string); try { stringRef.disableCollection(); return stringRef; } catch (ObjectCollectedException e) { lastCause = e; } } throw new RuntimeException("Can''t create safe string reference", lastCause); }

He estado escribiendo un cliente Java que usa JDI para crear y modificar objetos en una JVM remota (conectándose a un servidor JDWP basado en agentes que se ejecuta en la JVM remota). Uno de los requisitos de mi proyecto es que no puedo suspender todos los subprocesos en la JVM remota, lo que significa que los objetos que creo pueden ser susceptibles a la recolección de basura antes de poder hacerlos accesibles dentro de la JVM.

En algunos casos, estoy creando objetos en una JVM remota pero están siendo recolectados de forma aleatoria. Por ejemplo, si creo una matriz en la JVM remota a través de ArrayType.newInstance(int) , a veces la matriz se recolectará como basura antes de que pueda hacer que sea "alcanzable" desde otro objeto alcanzable en la JVM remota.

(Por ejemplo, si estoy tratando de almacenar la nueva matriz en un campo de un objeto alcanzable existente, la llamada a ObjectReference.setValue(Field, Value) puede lanzar aleatoriamente una ObjectCollectedException ):

void createAndStoreArray(ObjectReference reachableObj, Field fieldOfObj, ArrayType type, int length) { ArrayReference ref = type.newInstance(length); reachableObj.setValue(fieldOfObj, ref); // Sometimes throws ObjectCollectedException because ref''s mirror garbage gets collected before I can store it on the reachable object }

En teoría, el espejo de ObjectReference podría incluso recoger basura antes de que pueda llamar a ObjectReference.disableCollection() (que es un paso que no quiero tomar por otros motivos de todos modos).

Entonces mi pregunta es , ¿hay garantías de por vida documentadas en JDI Value ?

  • ¿Está un reflejo de un valor primitivo exento de GC en la JVM remota? (Uno supone que lo sería, pero ninguno de los documentos de métodos de VirtualMachine . mirror*() VirtualMachine . mirror*() dice nada).
  • ¿Está exento de GC un espejo de un String ? (Uno pensaría que no, pero el JavaDoc parece estar en silencio).
  • ¿Asumo que cualquier otra ObjectReference puede ser GC''d en cualquier momento a menos que logre desactivar GC en ella antes?

¡Gracias de antemano por tu ayuda!