一、概念
1. 內存泄漏:對象使用完之后,沒有按照預期被GC回收,一直留在內存中
2. 內存溢出:大量對象一直留在內存中,導致內存不夠用(OOM),影響正常的程序運行
二、內存泄漏的場景
1. 內存中數據量太大,比如一次性從數據庫中取出來太多數據
2. 靜態集合類中對對象的引用,在使用完后未清空(只把對象設為null,而不是從集合中移除),使JVM不能回收,即內存泄漏
3. 靜態方法中只能使用全局靜態變量,而如果靜態變量又持有靜態方法傳入的參數對象的引用,會引起內存泄漏
4. 代碼中存在死循環,或者循環過多,產生過多的重復的對象
5. JVM啟動參數內存值設置過小
a. 堆內存:JVM默認為64M,-Xms堆的最小值, -Xmx堆的最大值,OutOfMemoryError: java heap space
b. 棧內存:-Xss,StackOverflowError,棧太深
c. 永久代內存:-XX:PermSize,-XX:MaxPermSize,OutOfMemoryError: PermGen space,加載的類過多
6. 監聽器:addXXListener,沒有remove
7. 各種連接沒有關閉:例如數據庫連接、網絡連接
8. 單例模式:如果單例對象持有外部對象的引用,那么外部對象將不會被回收,引起內存泄漏
9. 一個類含有靜態變量,這個類的對象就無法被回收
10. ThreadLocal
三、解決思路
1. 修改JVM啟動參數,直接增加內存
2. 檢查錯誤日志
3. 檢查代碼中有沒有一次性查出數據庫所有數據
4. 檢查代碼中是否有死循環
5. 檢查代碼中循環和遞歸是否產生大量重復對象
6. 檢查List/Map等集合,是否未清除
7. 使用內存查看工具
四、代碼優化
1. 主動釋放無用的對象
2. 盡量使用StringBuilder代替String
3. 盡量少用靜態變量,因為靜態變量是類的,GC不會回收
4. 避免創建大對象和同時創建多個對象,例如數組,因為數組的長度是固定的
5. 對象池技術
五、JVM堆內存溢出后,其他線程可否繼續工作?
1. 當前線程OOM后,如果終止,會發生GC,其他線程可以繼續工作
2. 如果線程OOM后,沒有終止,其他線程也會OOM
https://www.cnblogs.com/200911/p/3965108.html