更新時間:2022-12-29 11:44:47 來源:動力節(jié)點 瀏覽2136次
大家在進(jìn)行Java開發(fā)的時候會遇到Java內(nèi)存泄露的情況,那么,Java內(nèi)存泄露的原因有哪些?下面來我們就來給大家講解一下。

每當(dāng)創(chuàng)建連接或者打開流時,JVM都會為這些資源分配內(nèi)存。如果沒有關(guān)閉連接,會導(dǎo)致持續(xù)占有內(nèi)存。在任意情況下,資源留下的開放連接都會消耗內(nèi)存,如果我們不處理,就會降低性能,甚至OOM。
解決辦法:使用finally塊關(guān)閉資源;關(guān)閉資源的代碼,不應(yīng)該有異常;jdk1.7后,可以使用try-with-resource塊。
大量使用static字段會潛在的導(dǎo)致內(nèi)存泄露,在Java中,靜態(tài)字段通常擁有與整個應(yīng)用程序相匹配的生命周期。
解決辦法:最大限度的減少靜態(tài)變量的使用;單例模式時,依賴于延遲加載對象而不是立即加載方式。
非靜態(tài)內(nèi)部類的初始化,總是需要外部類的實例;默認(rèn)情況下,每個非靜態(tài)內(nèi)部類都包含對其包含內(nèi)的隱式引用,如果我們在應(yīng)用程序中使用這個內(nèi)部類對象,那么即使在我們的包含類對象超出范圍后,它也不會被垃圾收集。
解決辦法:如果內(nèi)部類不需要訪問包含的類成員,考慮轉(zhuǎn)換為靜態(tài)類。
在HashMap和HashSet這種集合中,常常用到equal()和hashCode()來比較對象,如果重寫不合理,將會成為潛在的內(nèi)存泄露問題。
解決辦法:用最佳的方式重寫equals()和hashCode。
如果我們讀取一個很大的String對象,并調(diào)用了inter(),那么它將放到字符串池中,位于PermGen中,只要應(yīng)用程序運(yùn)行,該字符串就會保留,這就會占用內(nèi)存,可能造成OOM。
解決辦法:增加PermGen的大小,-XX:MaxPermSize=512m;升級Java版本,JDK1.7后字符串池轉(zhuǎn)移到了堆中。
使用ThreadLocal時,每個線程只要處于存貨狀態(tài)就可保留對其ThreadLocal變量副本的隱式調(diào)用,且將保留其自己的副本。使用不當(dāng),就會引起內(nèi)存泄露。
一旦線程不在存在,ThreadLocals就應(yīng)該被垃圾收集,而現(xiàn)在線程的創(chuàng)建都是使用線程池,線程池有線程重用的功能,因此線程就不會被垃圾回收器回收。所以使用到ThreadLocals來保留線程池中線程的變量副本時,ThreadLocals沒有顯示的刪除時,就會一直保留在內(nèi)存中,不會被垃圾回收。
解決辦法:不在使用ThreadLocal時,調(diào)用remove()方法,該方法刪除了此變量的當(dāng)前線程值。不要使用ThreadLocal.set(null),它只是查找與當(dāng)前線程關(guān)聯(lián)的Map并將鍵值對設(shè)置為當(dāng)前線程為null。
重寫finalize()方法時,該類的對象不會立即被垃圾收集器收集,如果finalize()方法的代碼有問題,那么會潛在的引發(fā)OOM;
解決辦法:避免重寫finalize()。
java內(nèi)存泄漏是java常見異常的一種,我們遇到這種情況的時候,需要及時進(jìn)行排查,知道錯誤的源頭才能進(jìn)行快速解決!
相關(guān)閱讀

初級 202925

初級 203221

初級 202629

初級 203743