programacion - ¿Cómo hacer que las referencias suaves se eliminen en Java?
manual de programacion android pdf (10)
Tengo un caché que tiene referencias suaves a los objetos en caché. Estoy tratando de escribir una prueba funcional para el comportamiento de las clases que usan la memoria caché específicamente para lo que ocurre cuando se eliminan los objetos en caché.
El problema es: parece que no se pueden eliminar las referencias suaves de manera confiable. Simplemente usar un montón de memoria no funciona: obtengo una OutOfMemory antes de borrar cualquier referencia suave.
¿Hay alguna manera de hacer que Java limpie con más entusiasmo las referencias suaves?
Encontrado aquí :
"Sin embargo, está garantizado que todas las SoftReferences se borrarán antes de lanzar OutOfMemoryError, por lo que teóricamente no pueden causar un OOME".
Entonces, ¿esto significa que el escenario anterior DEBE significar que tengo una pérdida de memoria en alguna parte con alguna clase que contiene una referencia difícil en mi objeto en caché?
El problema es: parece que no se pueden eliminar las referencias suaves de manera confiable.
Esto no es exclusivo de SoftReferences. Debido a la naturaleza de la recolección de basura en Java, no hay garantía de que todo lo que sea recolectable sea recolectado en algún momento. Incluso con un simple código:
Object temp = new Object();
temp = null;
System.gc();
no hay garantía de que el Objeto instanciado en la primera línea sea basura recolectada en este punto, o de hecho en cualquier punto. Es simplemente una de las cosas con las que tienes que vivir en un lenguaje administrado por memoria, estás renunciando al poder declarativo sobre estas cosas. Y sí, eso puede dificultar la prueba definitiva de fugas de memoria a veces.
Dicho esto, según los Javadocs que citó, SoftReferences definitivamente debe borrarse antes de lanzar un OutOfMemoryError (de hecho, ese es el punto completo de ellos y la única forma en que difieren de las referencias de objetos predeterminadas). Por lo tanto, suena como si hubiera algún tipo de pérdida de memoria en el sentido de que está reteniendo referencias más difíciles a los objetos en cuestión.
Si usa la -XX:+HeapDumpOnOutOfMemoryError
en la JVM, y luego carga el volcado del heap en algo como jhat , debería poder ver todas las referencias a sus objetos y así ver si hay alguna referencia al lado de las soft. Alternativamente, puede lograr lo mismo con un generador de perfiles mientras se ejecuta la prueba.
De la documentación y mi experiencia yo diría que sí: debes tener una referencia en otro lugar.
Sugiero usar un depurador que pueda mostrarle todas las referencias a un objeto (como Eclipse 3.4 al depurar Java 6) y simplemente verificar cuándo se lanza el OOM.
En una implementación típica de JVM (SUN), debe activar un GC completo más de una vez para limpiar las referencias suaves. La razón de esto es porque Softreferences requiere que el GC haga más trabajo, debido, por ejemplo, a un mecanismo que le permite recibir notificaciones cuando se reclaman los objetos.
En mi humilde opinión, el uso de muchas sofreferencias en un servidor de aplicaciones es malo, porque el desarrollador no tiene mucho control sobre cuándo se lanzaron.
La recolección de basura y otras referencias, como las referencias suaves, no son deterministas; no es posible hacer cosas confiables de manera que las referencias suaves se borren definitivamente en ese punto, por lo que su prueba puede juzgar cómo reacciona su caché. Sugeriría que simule el aclarado de referencia de una manera más definida burlándose, etc. Sus pruebas serán reproducibles y más valiosas en lugar de solo Hopi g para que el GC limpie las referencias. Usar este último enfoque es algo muy malo que hacer y solo presentará problemas adicionales en lugar de ayudarlo a mejorar la calidad de su caché y sus componentes colaboradores.
Si realmente deseaba, puede llamar a clear () en su SoftReference para borrarlo.
Dicho esto, si la JVM está lanzando un OutOfMemoryError y su SoftReference no se ha borrado aún, entonces esto significa que debe tener una referencia difícil al objeto en otro lugar. De lo contrario, invalidaría el contrato de SoftReference. De lo contrario, nunca se garantiza que se borre SoftReference: mientras haya memoria disponible, la JVM no necesita borrar ninguna referencia suave. Por otro lado, está permitido borrarlos la próxima vez que haga un ciclo de GC, incluso si no es necesario.
Además, puede considerar buscar en WeakReferences ya que el VM tiende a ser más agresivo para borrarlos. Técnicamente, nunca se requiere que la máquina virtual limpie una WeakReference, pero se supone que debe limpiarlos la próxima vez que haga un ciclo de GC si el objeto se consideraría muerto. Si estás intentando probar lo que sucede cuando se borra tu caché, usar WeakReferences debería ayudar a que tus entradas desaparezcan más rápido.
Además, recuerde que ambos dependen de que la JVM realice un ciclo de GC. Lamentablemente, no hay forma de garantizar que alguna de esas cosas ocurra. Incluso si llama a System.gc (), el recolector de basura puede decidir que está haciendo melocotón y decide no hacer nada.
Si usa eclipse, existe una herramienta llamada Memory Analyzer que facilita la depuración del volcado de pila.
Si tiene un caché que es un Mapa de SoftReferences y desea que se borren, puede borrar () el mapa y se limpiarán (incluidas sus referencias)
También está el siguiente parámetro de JVM para ajustar cómo se manejan las referencias suaves:
-XX:SoftRefLRUPolicyMSPerMB=<value>
Donde ''valor'' es el número de milisegundos, una referencia suave permanecerá por cada Mb de memoria libre. El valor predeterminado es 1s / Mb, por lo que si un objeto solo es accesible, durará 1 s si solo 1Mb de espacio en el montón está libre.
¿El objeto en caché tiene un finalizador? El finalizador creará nuevas referencias fuertes al objeto, por lo que incluso si se borra la referencia suave, la memoria no se recuperará hasta un ciclo de GC posterior
Puede obligar a todas las SoftReferences a borrarse en sus pruebas con este fragmento de código .