當(dāng)你從c&c++轉(zhuǎn)到一門具有垃圾回收功能的語(yǔ)言時(shí),程序員的工作就會(huì)變得更加容易,因?yàn)槟阌猛陮?duì)象,他們會(huì)被自動(dòng)回收,但是,java程序員真的不需要考慮內(nèi)存泄露嗎? 其實(shí)不然
1.舉個(gè)例子-看你能否找出內(nèi)存泄漏
import java.util.Arrays;public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if (size == 0) throw new EmptyStackException(); return elements[--size]; } private void ensureCapacity() { if (elements.length == size) elements = Arrays.copyOf(elements, 2 * size + 1); } }
1.1原因分析
上述程序并沒(méi)有明顯的錯(cuò)誤,但是這段程序有一個(gè)內(nèi)存泄漏,隨著GC活動(dòng)的增加,或者內(nèi)存占用的不斷增加,程序性能的降低就會(huì)表現(xiàn)出來(lái),嚴(yán)重時(shí)可導(dǎo)致內(nèi)存泄漏,但是這種失敗情況相對(duì)較少。
代碼的主要問(wèn)題在pop函數(shù),下面通過(guò)這張圖示展現(xiàn)
假設(shè)這個(gè)棧一直增長(zhǎng),增長(zhǎng)后如下圖所示
當(dāng)進(jìn)行大量的pop操作時(shí),由于引用未進(jìn)行置空,gc是不會(huì)釋放的,如下圖所示
從上圖中看以看出,如果棧先增長(zhǎng),在收縮,那么從棧中彈出的對(duì)象將不會(huì)被當(dāng)作垃圾回收,即使程序不再使用棧中的這些隊(duì)象,他們也不會(huì)回收,因?yàn)闂V腥匀槐4孢@對(duì)象的引用,俗稱過(guò)期引用,這個(gè)內(nèi)存泄露很隱蔽。