面试官:过期引用你了解吗?
共 2817字,需浏览 6分钟
·
2020-08-12 10:39
学过JVM的小伙伴一定知道JVM中的四大引用,分别是强引用,软引用,弱引用,虚引用。今天就来给大家说说什么是过期引用?
垃圾回收和内存分配是JVM的两大重点,今天通过一个过期引用的小例子串联起这两块的知识。
先上代码
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);
}
}
}
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);
}
}
首先创建了一个栈,栈的内部使用使用数组来实现,其中有两个操作,入栈和出栈,顺序入栈,倒置出栈。在Main函数中 for 循环先放入1000个元素,15s后 出栈500个元素。
对于我们来说 对于出栈的元素,我们往往不会再次从栈内获得。所以上面释放的500个元素 应该在之后被垃圾回收,但是通过Jprofiler工具,我发现在堆中 还是拥有1000个元素。原因是:stack栈中数组500到1000仍保存着释放对象的引用,使得500个对象引用成为过期引用。无法被GC 判断为无用对象进行回收。
如果想要对这些对象进行回收 只需要将pop方法中的数组引用指向为null,在一段时间后系统便会对500个对象进行回收。
总结一下
过期引用指的是永远不会被解除的引用
在我们的stack例子中,凡是在elements数组的”活动范围“之外的任何引用都是过期的,这里的活动部分指的是elements中下标小于size的那些元素。
过期引用导致的问题
过期引用会导致内存泄漏,内存泄露,所谓泄露,就是原来被分配后的内存,在失去利用价值后,应该还给系统以重复利用,但却没还给系统,导致系统可用内存越来越少。
GC如何判断一个对象是否可以回收,使用两种方式,一种是引用计数算法和可达性分析算法,引用计数算法 有着引用之间相互嵌套风险,所以可达性分析算法为主要使用,GC root链中对象对象可达则无法被回收,若多个对象和数组对象 有关,那么垃圾回收机制不仅不会处理这个对象,而且也不会处理被这个对象所引用的其他对象。即使只有少量几个对象引用被无意识的保留下来,也会有许许多多的对象被排除在垃圾回收机制之外。从而对性能造成潜在的巨大影响。
java源码中为避免过期引用如何实现
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
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 */
}
stack类继承vector类 进入vector类中可以看到最后一行代码,以及它的注释。
作者:Deciscive
链接:juejin.im/post/6844904071657160711