我剛剛接受采訪,并被要求使用Java造成記憶體泄漏,
不用說,我對如何開始創建它一無所知,
一個例子是什么?
解決方案:
這是在純Java中創建真正的記憶體泄漏(運行代碼無法訪問但仍存盤在記憶體中的物件)的好方法:
- 該應用程式創建一個長時間運行的執行緒(或使用執行緒池更快地泄漏),
- 執行緒通過(可選,自定義)加載類
ClassLoader, - 該類分配大量的記憶體(例如
new byte[1000000]),在靜態欄位中存盤對它的強參考,然后在中存盤對自身的參考ThreadLocal,分配額外的記憶體是可選的(泄漏類實體就足夠了),但這將使泄漏作業快得多, - 該應用程式清除對自定義類或
ClassLoader從中加載的所有參考, - 重復,
由于該方法ThreadLocal是在Oracle的JDK中實作的,因此會造成記憶體泄漏:
- 每個
Thread都有一個私有欄位threadLocals,該欄位實際存盤執行緒區域值, - 該映射中的每個鍵都是對
ThreadLocal物件的弱參考,因此在對該ThreadLocal物件進行垃圾回收之后,其條目將從映射中洗掉, - 但是每個值都是一個強參考,因此,當一個值(直接或間接)指向
ThreadLocal作為其鍵的物件時,只要執行緒存在,該物件就不會被垃圾回識訓從映射中洗掉,
在此示例中,強參考鏈如下所示:
Thread物件→threadLocals地圖→示例類的實體→示例類→靜態ThreadLocal欄位→ThreadLocal物件,
(ClassLoader在創建泄漏中并沒有真正起作用,它只是由于以下附加參考鏈而使泄漏更糟:示例類→→ClassLoader它已加載的所有類,在許多JVM實作中,甚至在更糟糕的情況下,情況甚至更糟, Java 7,因為類和ClassLoaders是直接分配到permgen中的,并且根本不會被垃圾回收,)
這種模式的一種變化是,如果您頻繁地重新部署碰巧使用ThreadLocals的應用程式,而應用程式容器(例如Tomcat)像sieve那樣以某種方式指向自身,那么它可以像篩子一樣泄漏記憶體,發生這種情況的原因可能有很多微妙,而且通常很難除錯和/或修復,
更新:由于很多人一直在要求它,所以這里有一些示例代碼顯示了這種行為,
本文首發于java黑洞網,博客園同步更新
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/283103.html
標籤:其他
上一篇:python將位元組轉換為字串
