面試官:過期引用你瞭解嗎?說說看...






今天給大家講講過期引用是個啥?學過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


分享到:


相關文章: