日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java thread 内存泄露_Java ThreadLocal 内存泄露问题分析及解决方法。

發布時間:2024/4/19 java 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java thread 内存泄露_Java ThreadLocal 内存泄露问题分析及解决方法。 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

在分析ThreadLocal導致的內存泄露前,需要普及了解一下內存泄露、強引用與弱引用以及GC回收機制,這樣才能更好的分析為什么ThreadLocal會導致內存泄露呢?更重要的是知道該如何避免這樣情況發生,增強系統的健壯性。

內存泄露

內存泄露為程序在申請內存后,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積后果很嚴重,無論多少內存,遲早會被占光,

廣義并通俗的說,就是:不再會被使用的對象或者變量占用的內存不能被回收,就是內存泄露。

強引用與弱引用

強引用,使用最普遍的引用,一個對象具有強引用,不會被垃圾回收器回收。當內存空間不足,Java虛擬機寧愿拋出OutOfMemoryError錯誤,使程序異常終止,也不回收這種對象。

如果想取消強引用和某個對象之間的關聯,可以顯式地將引用賦值為null,這樣可以使JVM在合適的時間就會回收該對象。

弱引用,JVM進行垃圾回收時,無論內存是否充足,都會回收被弱引用關聯的對象。在java中,用java.lang.ref.WeakReference類來表示??梢栽诰彺嬷惺褂萌跻谩?/p>

GC回收機制-如何找到需要回收的對象

JVM如何找到需要回收的對象,方式有兩種:引用計數法:每個對象有一個引用計數屬性,新增一個引用時計數加1,引用釋放時計數減1,計數為0時可以回收,

可達性分析法:從 GC Roots 開始向下搜索,搜索所走過的路徑稱為引用鏈。當一個對象到 GC Roots 沒有任何引用鏈相連時,則證明此對象是不可用的,那么虛擬機就判斷是可回收對象。引用計數法,可能會出現A 引用了 B,B 又引用了 A,這時候就算他們都不再使用了,但因為相互引用 計數器=1 永遠無法被回收。

ThreadLocal的內存泄露分析

先從前言的了解了一些概念(已懂忽略),接下來我們開始正式的來理解ThreadLocal導致的內存泄露的解析。

實現原理

static?class?ThreadLocalMap?{

static?class?Entry?extends?WeakReference>?{

/**?The?value?associated?with?this?ThreadLocal.?*/

Object?value;

Entry(ThreadLocal>?k,?Object?v)?{

super(k);

value?=?v;

}

}

...

}

ThreadLocal的實現原理,每一個Thread維護一個ThreadLocalMap,key為使用弱引用的ThreadLocal實例,value為線程變量的副本。這些對象之間的引用關系如下,

實心箭頭表示強引用,空心箭頭表示弱引用

ThreadLocal 內存泄漏的原因

從上圖中可以看出,hreadLocalMap使用ThreadLocal的弱引用作為key,如果一個ThreadLocal不存在外部強引用時,Key(ThreadLocal)勢必會被GC回收,這樣就會導致ThreadLocalMap中key為null, 而value還存在著強引用,只有thead線程退出以后,value的強引用鏈條才會斷掉。

但如果當前線程再遲遲不結束的話,這些key為null的Entry的value就會一直存在一條強引用鏈:Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value

永遠無法回收,造成內存泄漏。

那為什么使用弱引用而不是強引用??

我們看看Key使用的

key 使用強引用

當hreadLocalMap的key為強引用回收ThreadLocal時,因為ThreadLocalMap還持有ThreadLocal的強引用,如果沒有手動刪除,ThreadLocal不會被回收,導致Entry內存泄漏。

key 使用弱引用

當ThreadLocalMap的key為弱引用回收ThreadLocal時,由于ThreadLocalMap持有ThreadLocal的弱引用,即使沒有手動刪除,ThreadLocal也會被回收。當key為null,在下一次ThreadLocalMap調用set(),get(),remove()方法的時候會被清除value值。

ThreadLocalMap的remove()分析

在這里只分析remove()方式,其他的方法可以查看源碼進行分析:

private?void?remove(ThreadLocal>?key)?{

//使用hash方式,計算當前ThreadLocal變量所在table數組位置

Entry[]?tab?=?table;

int?len?=?tab.length;

int?i?=?key.threadLocalHashCode?&?(len-1);

//再次循環判斷是否在為ThreadLocal變量所在table數組位置

for?(Entry?e?=?tab[i];

e?!=?null;

e?=?tab[i?=?nextIndex(i,?len)])?{

if?(e.get()?==?key)?{

//調用WeakReference的clear方法清除對ThreadLocal的弱引用

e.clear();

//清理key為null的元素

expungeStaleEntry(i);

return;

}

}

}

再看看清理key為null的元素expungeStaleEntry(i):

總結

以上是生活随笔為你收集整理的java thread 内存泄露_Java ThreadLocal 内存泄露问题分析及解决方法。的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。