- <strong>
- <strong>
- <strong>
- <strong>
- <strong>
今天給大家講講過期引用是個啥?學過JVM的小夥伴一定知道JVM中的四大引用,分別是強引用,軟引用,弱引用,那麼今天就來給大家說說什麼是過期引用
垃圾回收和內存分配是JVM的兩大重點,今天通過一個過期引用的小例子串聯起這兩塊的知識。
先上代碼
<code>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) { ensureCapcity(); elements[size++]=e; } public Object pop(){ if(size==0){ throw new EmptyStackException(); } return elements[--size]; //Object result=elements[--size]; //elements[size]=null; //return result; } private void ensureCapcity(){ if(elements.length==size){ elements= Arrays.copyOf(elements,2*size+1); } }}/<code>
<code>public class JprofilerUserTestMain { public static void main(String[] args) throws InterruptedException { //工具測試主類 Stack stack=new Stack(); for (int i = 0; i < 1000; i++) { MyClass myClass=new MyClass(i,""+i,(long)i); stack.push(myClass); } //等待15s Thread.sleep(15000); for (int i = 0; i < 500; i++) { stack.pop(); } Thread.sleep(1000000); }}/<code>
首先創建了一個棧,棧的內部使用使用數組來實現,其中有兩個操作,入棧和出棧,順序入棧,倒置出棧。在Main函數中 for 循環先放入1000個元素,15s後 出棧500個元素。
對於我們來說 對於出棧的元素,我們往往不會再次從棧內獲得。所以上面釋放的500個元素 應該在之後被垃圾回收,但是通過Jprofiler工具,我發現在堆中 還是擁有1000個元素。 原因是:stack棧中數組500到1000仍保存著釋放對象的引用,使得500個對象引用成為過期引用。無法被GC 判斷為無用對象進行回收。
如果想要對這些對象進行回收 只需要將pop方法中的數組引用指向為null,在一段時間後系統便會對500個對象進行回收。
總結一下
過期引用指的是永遠不會被解除的引用
在我們的stack例子中,凡是在elements數組的”活動範圍“之外的任何引用都是過期的,這裡的活動部分指的是elements中下標小於size的那些元素。
過期引用導致的問題
過期引用會導致內存洩漏,內存洩露,所謂洩露,就是原來被分配後的內存,在失去利用價值後,應該還給系統以重複利用,但卻沒還給系統,導致系統可用內存越來越少。
GC如何判斷一個對象是否可以回收,使用兩種方式,一種是引用計數算法和可達性分析算法,引用計數算法 有著引用之間相互嵌套風險,所以可達性分析算法為主要使用,GC root鏈中對象對象可達則無法被回收,若多個對象和數組對象 有關,那麼垃圾回收機制不僅不會處理這個對象,而且也不會處理被這個對象所引用的其他對象。即使只有少量幾個對象引用被無意識的保留下來,也會有許許多多的對象被排除在垃圾回收機制之外。從而對性能造成潛在的巨大影響。
java源碼中為避免過期引用如何實現
<code>public synchronized E pop() { E obj; int len = size(); obj = peek(); removeElementAt(len - 1); return obj;}/<code>
<code>public synchronized void removeElementAt(int index) { modCount++; if (index >= elementCount) { throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); } else if (index < 0) { throw new ArrayIndexOutOfBoundsException(index); } int j = elementCount - index - 1; if (j > 0) { System.arraycopy(elementData, index + 1, elementData, index, j); } elementCount--; elementData[elementCount] = null; /* to let gc do its work */}/<code>
stack類繼承vector類 進入vector類中可以看到最後一行代碼,以及它的註釋。
作者:cpp-wen
原文鏈接:https://juejin.im/post/5e547264e51d4526de3927be
閱讀更多 追逐仰望星空 的文章