Конечная статья ThreadLocal: в чем причина утечки памяти ThreadLocal?

Java EE

Недавно я наблюдал утечку памяти ThreadLocal, и мнений в Интернете много. Самой популярной является утечка памяти, вызванная слабыми ссылками.

почему утечка памяти

1. При каких обстоятельствах ThreadLocal перерабатывается

ThreadLocalсуществуетThreadLocalMapна него ссылается ключ в записи как на слабую ссылку.ThreadLocalБудет ли он переработан?

Здесь используются упомянутые точки знаний. существуетЧетыре ссылки на javaсказал. Когда на объект указывает сильная ссылка (в данном случае достижимая). Сборщик мусора не будет его перерабатывать.

Например

ThreadLocal threadlocal1 = new ThreadLocal();
threadlocal1.set("测试");

ThreadLocalТеперь объект имеет два индекса, на которые он указывает.

  • Сильная цитата:threadlocal1В соответствии с рисунком [1]
  • Слабая ссылка:Key(WeakReference(threadlocal1))Соответствует [2] на рисунке

Поэтому, когда происходит GC, объект ThreadLocal в куче не будет переработан.

Но когда мы ставимthreadlocal1 =null;При нарушении сильной ссылки, в это времяThreadLocaОбъект l имеет только одну слабую ссылку, поэтому при сборке мусораThreadLocalобъект перерабатывается,Entryстановится ключом с нулемEntry. Также называется грязным входом

особенность:

  • Ключ нулевой, и приложение не может получить доступ к значению, потому что у нас нет на него ссылки.
  • Thread Ref -> Thread -> ThreaLocalMap -> Entry -> valueЦепочка существует, а текущий поток задерживается (например пул потоков), но их нельзя использовать, они становятся грязными данными, что приводит к утечке памяти.

Похоже на утечку памяти, вызванную мягкой ссылкой.


2. Зачем использовать слабые ссылки

Затем проведите сильный эталонный анализ:ThreadLocalна объект указывают две сильные ссылки

  • Сильная ссылка: threadlocal1
  • Сильная ссылка: Entry.key

Когда мы ломаем сильную ссылку в программеthreadlocal1Время.ThreadLocalОбъект по-прежнему имеет сильную ссылкуEntry.keyуказывают на, не будут переработаны, в результате чего,ThreadLocalобъект сvalueстановятся грязными данными.


Сравните эти два случая:Независимо от мягких ссылок или сильных ссылок могут возникать утечки памяти, но слабые ссылки уменьшают степень утечек памяти.

использование слабых ссылокЗапись будет иметь особенность, что ключ является нулевым, вы можете определить, какие данные не используются, выполнить операции очистки, слабые ссылки Вместо этого он повышает безопасность ThreadLocal.

На самом деле при вызовеThreadLocalизget(),set(),reomve()метод, очистит потокThreadLocalMapВо всех записях значение ключа равно null, и вся запись имеет значение null, что полезно для следующего восстановления памяти.

3. Истинная причина утечки

Итак: настоящая причина утечки памяти ThreadLocal:

  1. ThreadLocalMapЖизненный цикл Thread такой же длинный, как и у Thread.Если пул потоков не удаляется, например, пул потоков, это может привести к утечке памяти.
  2. Если его вовремя не очистить после использования, он больше не будет вызыватьсяget()、set()、remove()Очистите грязные записи

Это настоящая причина утечки памяти.

Суммировать:

Удалить вовремя после использования - самый аутентичный способ использования.

Если есть какие-либо ошибки, сообщите нам об этом и учитесь вместе.

Ссылаться на: