2012-02-06 8 views
7

Javadocs dice "Cuando una clave ha sido descartada su entrada es efectivamente eliminado del mapa".WeakHashMap y el valor fuertemente referenciado

Pero a menos que haya otro hilo que ocasionalmente elimina tales Map.Entry entradas, serán los objetos de valor no estar fuertemente referenciados por el mapa? Pero dado que no se está ejecutando dicho subproceso, solo las invocaciones de método get pueden eliminar tales entradas, una a la vez.

Casi siempre uso WeakHashMap<K, WeakReference<V>> por esa razón. ¿Por qué no habrían hecho eso el comportamiento predeterminado? ¿Los valores también son referencias débiles?

+0

http://stackoverflow.com/questions/2473410/question-about-weakhashmap es una pregunta casi idéntica. Pero quería saber si mi afirmación es correcta: una entrada será eliminada solo cuando get() descubra que la clave ha sido gc'ed, lo que francamente no parece ser de gran valor a menos que use WeakReferences como valores. –

+0

Sí, es solo encuestado. Si quieres algo diferente, escribe tu propia versión. –

+2

Si necesita algo diferente, use una biblioteca; escribir la suya es súper complicado. Guava tiene 'MapMaker', que le permite configurar la fuerza de las referencias clave y de valor: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/MapMaker. html –

Respuesta

8

colas de referencia se utilizan para eliminar automáticamente entradas.

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/ReferenceQueue.html

colas de referencia, con la que registró objetos de referencia se adjuntan, al recolector de basura después se detectan los cambios de accesibilidad apropiados.

Básicamente, las referencias débiles son una parte fundamental del recolector de basura, por lo que cuando un barrido GC sucede, las referencias no utilizadas se encuentran y se ponen en colas y luego medidas pueden adoptarse basándose en el contenido de esas colas.

Un hilo se puede sentar en el método remove de la cola para recibir una alerta cuando es necesario realizar una limpieza o poll en la cola.

"Java theory and practice: Plugging memory leaks with weak references" explica:

La implementación de WeakHashMap ilustra un lenguaje común con referencias débiles - que algún objeto interno se extiende WeakReference.

...

WeakHashMap utiliza referencias débiles para la celebración de las llaves de mapas, que permite que los objetos fundamentales que se recogen la basura cuando ya no son utilizados por la aplicación, y la aplicación get() puede decir un mapeo directo desde una muerto por si WeakReference.get() devuelve null. Pero esto es solo la mitad de lo que se necesita para evitar que el consumo de memoria de un Mapa aumente a lo largo de la vida útil de la aplicación; también se debe hacer algo para podar las entradas muertas del Mapa una vez que se ha recopilado el objeto clave. De lo contrario, el mapa simplemente se llenaría con las entradas correspondientes a las claves muertas. Y si bien esto sería invisible para la aplicación, todavía podría hacer que la aplicación se ejecute sin memoria debido a que el Map.Entry y objetos de valor no serían recogidos, incluso si la clave es.

...

colas de referencia son los medios principales del colector de basura de retroalimentación de información a la aplicación sobre el ciclo de vida del objeto. Las referencias débiles tienen dos constructores: una toma solo el referente como argumento y la otra también toma una cola de referencia. Cuando una referencia débil ha sido creado con una cola de referencia asociado y el referente se convierte en un candidato para la GC, el objeto de referencia (no el referente) se pone en cola en la cola de referencia después de que se borre la referencia.La aplicación puede recuperar la referencia de la cola de referencia y aprender que el referente se ha recopilado para que pueda realizar actividades de limpieza asociadas, como eliminar las entradas de objetos que se han salido de una colección débil. (Colas de referencia ofrecen los mismos modos desencola como BlockingQueue - encuestados, el bloqueo temporizado, y el bloqueo sin hora.)

EDIT:

Incluso con colas, mapas débiles todavía puede tener fugas. Ephemerons son un intento de resolver el caso donde una tecla débil hace referencia a un valor fuertemente mantenido que hace referencia a la clave. No son implementables en Java.

Ephemerons resuelven un problema que se encuentra comúnmente al tratar de "adjuntar" propiedades a los objetos mediante el uso de un registro. Cuando se debe adjuntar una propiedad a un objeto, la propiedad debería (en términos de comportamiento del GC) tener típicamente el tiempo de vida que tendría una variable de instancia de este objeto. Sin embargo, esto se complica por tener una asociación externa entre el objeto y su propiedad, tales como:

property --------- registry --------- association --------- object 

Aquí, el registro (un tercero) se sostendrá sobre la propia asociación que requeriría la extracción manual del registro (en lugar de recolección de basura automatizada). Si bien este problema siempre puede resolverse en cualquier situación concreta utilizando uno de los varios tipos de asociaciones débiles, elegir el tipo de asociación "correcta" depende de una variedad de factores, algunos de los cuales pueden cambiar dinámicamente.

Los efemerones resuelven este problema al definir que los 'contenidos' (valor) de un efemerón se mantendrán con fuerza hasta que se sepa que la clave es basura recolectada. A partir de ese momento, el contenido del efemerón se mantendrá débilmente. Por lo tanto, los contenidos de un efemerón pueden ser elegibles para la recolección de basura si y solo si la clave es basura coleccionable, que es el comportamiento exacto que observaríamos para una variable de instancia del objeto.

+0

Olvidé la capacidad de la cola de referencia para llamar a nuestro propio gancho. –

+0

Encontré desde su enlace "WeakHashMap tiene un método privado llamado expungeStaleEntries() que se llama durante la mayoría de las operaciones de Map". ser útil. Y me pregunto si generar una secuencia que realmente haga lecturas de bloqueo en la cola de referencia podría ser una mejor idea. Tal vez eso es lo que hace el MapMaker de Guava. –

+1

@UstamanSangat, no sé qué hace MapMaker, pero quizás expungeStaleEntries() sondee la cola de referencia para amortizar la limpieza con el uso del mapa. Intentaría usar algo como MapMaker antes de dedicarme a implementar mi propia limpieza de claves.Por cierto, agregué una edición que indica maneras en que puedes perder memoria incluso usando mapas de teclas débiles. –

Cuestiones relacionadas