2009-10-28 12 views
15

Recientemente me encontré con un código de Java con WeakReferences: nunca los había visto desplegados, aunque me los encontré cuando se presentaron. ¿Es esto algo que debería usarse de forma rutinaria o solo cuando uno se encuentra con problemas de memoria? En este último caso, ¿se pueden adaptar fácilmente o el código necesita una refactorización seria? ¿Puede el programador promedio Java (o C#) generalmente ignorarlos?¿Cuándo se deben usar referencias débiles?

EDIT ¿Se puede causar algún daño por el uso excesivo de WR?

+0

Pareja más ejemplos de usos para referencias débiles en http://stackoverflow.com/questions/1434156/other-uses-of-weak-references –

+0

Por lo que sé, el único peligro con WR es que en realidad podría querer a * strong * referencia. Si tus objetos comienzan a desaparecer cuando no los quieres, es posible que hayas ido demasiado lejos;) –

+0

Debes saber cuándo usarlos y cómo, y en algunos casos se trata de problemas similares a los encontrados en el multihilo con bloqueo en datos. Por ejemplo, es simplemente incorrecto para una muestra (.NET): 'if (x.IsAlive) {x.Target.ToString(); } 'porque el objeto puede haber sido recolectado mientras tanto. Primero tiene que adquirir una referencia fuerte y luego verificar si todavía está viva: 'object t = x.Target; if (t! = null) {t.ToString(); } 'porque tan pronto como hayas vuelto a adquirir una referencia fuerte al objeto, no se recopilará. – Lucero

Respuesta

20

Las referencias débiles tienen que ver con la recolección de basura. Un objeto estándar no "desaparecerá" hasta que se corten todas las referencias a él, esto significa que todas las referencias de sus diversos objetos tienen que eliminarse antes de que la recolección de basura lo considere basura.

Con una referencia débil solo porque su objeto es referenciado por otros objetos no necesariamente significa que no es basura. Todavía puede ser recogido por GC y ser eliminado de la memoria.

Un ejemplo: si tengo un montón de objetos Foo en mi aplicación, me gustaría utilizar un conjunto para mantener un registro central de todos los Foo que tengo. Pero, cuando otras partes de mi aplicación eliminan un objeto Foo al eliminar todas las referencias, ¡no quiero que la referencia restante que mi Conjunto contiene para ese objeto evite que se recolecte basura! Realmente solo quiero que desaparezca de mi set. Aquí es donde usarías algo así como un conjunto débil (Java tiene un WeakHashMap) en su lugar, que utiliza referencias débiles a sus miembros en lugar de referencias "fuertes".

Si sus objetos no están siendo recogidos cuando lo desea, entonces ha cometido un error en su contabilidad, algo todavía contiene una referencia que olvidó eliminar. El uso de referencias débiles puede aliviar el dolor de dicha contabilidad, ya que no tiene que preocuparse de que mantengan un objeto "vivo" y sin recolección de basura, pero no tiene tiene para usarlos.

15

Los utiliza siempre que desee tener una referencia a un objeto sin mantener el objeto vivo usted mismo. Esto es cierto para muchas características similares a la del almacenamiento en caché, pero también desempeña un papel importante en el manejo de eventos, donde un suscriptor no se mantendrá vivo al estar suscrito a un evento.

Un pequeño ejemplo: un evento del temporizador que refresca algunos datos. Cualquier número de objetos puede suscribirse en el temporizador para recibir notificaciones, pero el simple hecho de que se suscribieron en el temporizador no debería mantenerlos vivos. Entonces el temporizador debería tener referencias débiles a los objetos.

+1

Usar referencias débiles (especialmente a través de 'WeakHashMap') puede ser terriblemente incorrecto. Por ejemplo, la VM puede notar que puede borrar las referencias casi inmediatamente después de que se crean. Esto sucede, aunque generalmente después de que la aplicación ha estado funcionando un tiempo. –

+1

tachado - No estoy seguro acerca de "horriblemente mal" - ciertamente si se usan cuando no deberían, entonces la aplicación fallará - pero eso es un problema de diseño, no tiene nada que ver con las referencias débiles per-se –

+0

I No estoy diciendo que deba hacer referencia a un objeto solo a través de una referencia débil, sino que puede usarlos para mantener referencias a objetos donde no es su responsabilidad mantenerlos vivos. Usualmente, esos objetos serán parte de un gráfico de objetos fuertemente referenciado, pero cuando ese gráfico sale del alcance, la referencia débil no debe impedir que el GC los recoja. Siempre es lo mismo: use las herramientas adecuadas donde quepan. – Lucero

7

¿Se puede hacer algún daño por uso excesivo de WR?

Sí, puede.

Una de las preocupaciones es que las referencias débiles hacen que su código sea más complicado y potencialmente propenso a errores. Cualquier código que use una referencia débil necesita tratar con la posibilidad de que la referencia se haya roto cada vez que la use. Si usa referencias débiles en exceso, termina escribiendo muchos códigos adicionales. (Puede mitigar esto ocultando cada referencia débil detrás de un método que se encarga de la verificación, y vuelve a crear el objeto descartado a pedido. Pero esto puede no ser necesariamente tan simple como eso, por ejemplo, si el proceso de recreación involucra a la red acceso, debe hacer frente a la posibilidad de una falla de recreación.)

Una segunda preocupación es que hay gastos generales de tiempo de ejecución con el uso de referencias débiles.Los costos obvios son los de crear referencias débiles y llamar al get. Un costo menos obvio es que se necesita hacer un trabajo adicional significativo cada vez que se ejecuta el GC.

Una última preocupación es que si utiliza referencias débiles para algo que es muy probable que necesite su aplicación en el futuro, puede incurrir en el costo de volver a crearla repetidamente. Si este costo es alto (en términos de tiempo de CPU, ancho de banda IO, tráfico de red, lo que sea) su aplicación puede funcionar mal como resultado. Puede que sea mejor darle a la JVM más memoria y no utilizar referencias débiles en absoluto.

Por supuesto, esto no significa que deba evitar el uso de referencias débiles por completo. Solo que necesitas pensar cuidadosamente. Y probablemente primero deba ejecutar un generador de perfiles de memoria en su aplicación para averiguar de dónde provienen sus problemas de uso de memoria.

1

Una buena pregunta al considerar el uso de una WeakReference es cómo se sentiría si la referencia débil se invalidara en el instante en que no existieran referencias sólidas para el objeto. Si eso hace que la WeakReference sea menos útil, entonces una WeakReference probablemente no sea la mejor opción. Si eso sería una mejora sobre la invalidación no determinista que proviene de la recolección de basura, entonces una WeakReference es probablemente la opción correcta.

Cuestiones relacionadas