works memories how eden java memory-management garbage-collection singleton

java - how - jvm memories



Auto liberador(recuento de referencias) singelton (2)

Considere la siguiente situación: tiene una clase singleton que representa algún tipo de proveedor de datos. Esta clase singleton asigna mucha memoria, y desea que libere su memoria asignada cuando no hay nadie que lo use. Fluir:

  1. Clase A llamada getInstance y utiliza singleton (esta es la primera vez que se llama a getInstance y la clase singleton asigna un gran fragmento de memoria)
  2. Clase B llamada getInstance y utiliza singleton
  3. Clase A y clase B "muere" (nadie usa singleton ahora)
  4. El programa aún se está ejecutando pero la memoria de Singleton no se ha liberado.

¿Cómo sugiere la implementación de singleton que en la etapa 3 (clase A y B "muere") liberará la memoria (sé que Java utiliza la recolección de basura, pero aún así decir que quiero la siguiente memoria = nulo).

PD: No quiero forzar a cada clase que usa el lanzamiento de llamada singleton en singleton cada vez que deja de usarlo. Quiero que Singleton maneje la memoria de "liberación" solo.


El uso del Design pattern: "Singleton" es muy común y la implementación común está utilizando una reference static .

El problema con esta implementación es que muchas veces deja floating garbage que no está en uso.

Por ejemplo: Un singleton que contiene un DB connection pool que solo necesita la aplicación al inicio para confingar la carga.

Por lo tanto, una mejor solución es una extensión del patrón de diseño de Singleton llamado WeakSingleton .

Este patrón es el esperado, cuando todas las demás referencias a la instancia original han expirado, la instancia se limpia.

Una implementación de este patrón en Java es muy simple y puede basarse en WeakReferences .

Por ejemplo, código:

public class WeakSingleton{ static private WeakReference singleton; // instance public WeakSingleton getInstance(){ WeakSingleton m = (WeakSingleton)singleton.get(); if( m != null) return m; synchronized (WeakSingleton.class){ m = (WeakSingleton)singleton.get(); if( m != null) return m; m = new WeakSingleton(); // creates new instnace singleton = new WeakReference(m); } return m; } }


Lo que puedes hacer es

  • solo crea el singleton la primera vez que se solicita.
  • almacenarlo en una WeakReference . Esto solo permanecerá vivo después de un GC si todavía tiene una referencia "fuerte" en otro lugar.

Si WeakReference.get() es null significa que se recopiló porque nadie lo estaba usando con fuerza, otra referencia débil no cuenta. Si es necesario nuevamente, debe recrearlo y WeakReference .

Me gusta esto,

public enum SingletonHolder{; // no instances private static WeakReference<MyType> ref = null; public static synchronized MyType getInstance() { MyType type = ref == null ? null : ref.get(); if (type == null) ref = new WeakReference<MyType>(type = new MyType()); return type; } }

Por cierto, esto supone que las instancias que necesitan esta instancia conservan una referencia a ella. Así es como la referencia débil "sabe" que todavía es necesaria.

BTW2 No necesita sincronización si tiene un solo hilo, pero debería ser inofensivo.

Esto significa que debe llamar a este método solo cuando una nueva instancia lo necesita por primera vez, no siempre y hacerlo más eficiente no debería hacer mucha diferencia, por ejemplo, la doble verificación simplemente lo complica.