內存泄露與內存溢出都會導致內存無法得到合理的使用,只是之間確實有些差異,容易混淆。
簡單來說,內存泄露是不需要存活的對象無法被回收佔用內存。內存溢出是必要的對象沒有足夠的內存來創建。
內存泄露
內存泄漏(memory leak ):是指程序在申請內存後,無法釋放已申請的內存空間就造成了內存泄漏,一次內存泄漏似乎不會有大的影響,但內存泄漏堆積後的後果就是內存溢出。
常見原因
當一個對象已經不需要再使用本該被回收時,另外一個正在使用的對象持有它的引用從而導致它不能被回收,這導致本該被回收的對象不能被回收而停留在堆內存中,這就產生了內存泄漏。
我的理解就是,因爲編碼問題,導致生命週期很短且本該回收的對象一直無法被gc。
舉個例子
靜態類實現單例模式。因爲其生命週期和應用的生命週期一樣長,所以如果在創建單例時,傳入了其他對象,則該對象將一直無法被回收。
/**
* 靜態類實現單例模式,如果傳入對象,則當前對象生命週期將與應用生命週期一致
*
* @author baijiaan
* @date 2020-05-27
*/
public class SingleInstanceTest {
private static SingleInstanceTest sInstance;
private OneObject oneObject;
private SingleInstanceTest(OneObject oneObject) {
this.oneObject = oneObject;
}
public static SingleInstanceTest newInstance(OneObject oneObject) {
if (sInstance == null) {
sInstance = new SingleInstanceTest(oneObject);
}
return sInstance;
}
}
內存溢出
內存溢出(out of memory): 指程序申請內存時,沒有足夠的內存供申請者使用,或者說,給了你一塊存儲int類型數據的存儲空間,但是你卻存儲long類型的數據,那麼結果就是內存不夠用,此時就會報錯OOM,即所謂的內存溢出,簡單來說就是自己所需要使用的空間比我們擁有的內存大,內存不夠使用所造成的內存溢出。
常見原因
內存溢出的原因比較寬泛:
- 可能是分配的內存本身就不夠
- 一次性裝載到內存的數據量過大
- 內存泄露使內存被不合理的佔用導致可用內存不夠
- 編碼問題,比如進入了一個循環創建對象的情況
解決方法
對應上面的常見原因,我們大概的解決思路是:
- 修改-Xmx
- 防止一次性加載過多數據
- 找OutOfMemory異常來定位問題出現位置
- 養成良好的編碼習慣
總結
個人理解,內存泄露是一種行爲,而內存溢出是一個結果。內存溢出這個結果出現了,那系統就不能正常使用了。而偶爾的內存泄露不可怕,頻繁的內存泄露可能會造成惡劣的後果。