El mecanismo ThreadLocal almacena efectivamente en el hilo actual un WeakHashMap de instancias de ThreadLocal en valores. En consecuencia, si la instancia de ThreadLocal nunca se vuelve débilmente referenciable, entonces la entrada se filtra de manera efectiva.
Hay dos casos a considerar. Por la simplicidad de la discusión, supongamos que ThreadLocal realmente almacena un WeakHashMap en Thread.currentThread(); en realidad, usa un mecanismo más sofisticado que tiene un efecto equivalente.
Primero en cuenta la situación "nueva Weakling":
- En la primera iteración del bucle:
- la clase Weakling se carga desde el cargador de clases del sistema
- el constructor Weakling se llama
- la variable estática Weakling.local se establece desde nulo en una nueva instancia ThreadLocal # 1
- ThreadLocal WeakHashMap se actualiza para almacenar la nueva instancia Weakling # 1
- En todas las iteraciones posteriores del bucle:
- la clase Weakling ya se carga desde el cargador de clases sistema
- el constructor Weakling se llama
- la variable estática Weakling.local se establece desde la instancia anterior ThreadLocal # 1 a una nueva instancia ThreadLocal # 2. La vieja instancia de ThreadLocal # 1 ahora es referenciada (débilmente) por WeakHashMap.
- ThreadLocal WeakHashMap se ha actualizado para almacenar la nueva instancia de Weakling. Durante esta operación, WeakHashMap nota que la instancia anterior ThreadLocal # 1 es solo de referencia débil, por lo que elimina la entrada [instancia ThreadLocal # 1, Weakling # 1] del Mapa antes de agregar la [instancia ThreadLocal # 2, Weakling # 2 ] entrada.
En segundo lugar consideran que la "nueva URLClassLoader (...). LoadClass (...).newInstance()" escenario:
- En la primera iteración del bucle: clase
- la Weakling # 1 se carga desde URLClassLoader # 1
- el constructor Weakling se llama
- la Weakling. local # 1 variable estática se establece desde nulo a una nueva instancia ThreadLocal # 1
- la ThreadLocal WeakHashMap se actualiza para almacenar la nueva instancia Weakling # 1
- En todas las iteraciones posteriores del bucle
- la #n clase Weakling se carga desde URLClassLoader #n
- el constructor Weakling se llama
- la Weakling.local #n variable estática se establece de NULL a una nueva instancia ThreadLocal #n
- ThreadLocal WeakHashMap se ha actualizado para almacenar la nueva instancia Weakling.
Tenga en cuenta que durante este paso final, instancia ThreadLocal # 1 es no débilmente referenciable. Esto es debido a la siguiente cadena de referencia:
- valor WeakHashMap referencia fuertemente Weakling ejemplo # 1
- Weakling ejemplo # 1 Referencias fuertemente Weakling clase # 1 a través de Object.getClass()
- Weakling clase # 1 fuertemente referencias ThreadLocal ejemplo # 1 a través de la clase variable estática
mientras el bucle continúa funcionando, se añaden más entradas a la ThreadLocal WeakHashMap, y la fuerte cadena de referencia de valor-a-clave (ejemplo Weakling a ThreadLocal) en el WeakH ashMap evita la recolección de basura de entradas que de otro modo estarían obsoletas.
He modificado el programa Loader para que se repita 3 veces y luego espere la entrada del usuario. Luego, generé un volcado de pila usando java -Xrunhprof: heap = dump y ctrl-pause/break. Lo que sigue es mi análisis de la final de volcado de pila:
En primer lugar, hay tres objetos Weakling:
OBJ 500002a1 (sz=16, trace=300345, [email protected])
OBJ 500003a4 (sz=16, trace=300348, [email protected])
OBJ 500003e0 (sz=16, trace=300342, [email protected])
Tenga en cuenta que los tres casos Weakling (500002a1, 500003a4 y 500003e0) se crean a partir de tres clases distintas instancias (50000296, 5000039d y 500003d9, respectivamente).Mirando el primer objeto, podemos ver que se lleva a cabo como un valor en un objeto entrada en el mapa ThreadLocal:
OBJ 500002a5 (sz=32, trace=300012, [email protected])
referent 500002a4
queue 500009f6
value 500002a1
El referente aquí es el valor que se celebra débilmente:
OBJ 500002a4 (sz=16, trace=300347, [email protected])
búsqueda, podemos ver que este objeto se lleva a cabo como un valor en la variable estática "local" de la clase mencionada Weakling:
CLS 50000296 (name=Weakling, trace=300280)
super 50000099
loader 5000017e
domain 50000289
static local 500002a4
static staticRef 500002a1
en conclusión, tenemos el siguiente fuerte bucle de cadena de referencia para esta instancia de debilitamiento, que evita que se recolecte basura.
- valor WeakHashMap (500002a5) hace referencia a fuertemente ejemplo Weakling (500002a1)
- ejemplo Weakling (500002a1) fuertemente referencias de clase Weakling (50,000,296) a través de Object.getClass()
- clase Weakling (50000296) Referencias fuertemente ThreadLocal instancia (500002a4) a través de la variable de clase estática
Un análisis similar en los otros objetos Weakling mostraría un resultado similar. Permitir que el programa se ejecute para iteraciones adicionales muestra que los objetos continúan acumulándose de esta manera.
Quizás pueda replantear su pregunta o aclarar qué parte de mi respuesta no comprende. –
He actualizado el comentario. –