以一个例子记录,对象引用对垃圾回收的影响情况。
/**
* -XX:MaxHeapSize=10m -XX:InitialHeapSize=10m -XX:+PrintGCDetails
*/
public class GCTest {
public byte[] bytes = new byte[1024*1000]; // 约1m
public static void main(String[] args) {
System.out.println("main start");
GCTest gcTest = new GCTest();
//gcTest = null; // 设置为null, 即表示为上面创建的对象解除引用;否则,即使调用了垃圾回收指令,对象也不会被回收
System.gc();//垃圾回收 , 相当于Runtime.getRuntime().gc();
try {
Thread.sleep(3000); // GC 线程优先级低,因此延迟,确保在退出主线程前,已经执行了垃圾回收
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main continue");
try {
Thread.sleep(10000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main end");
}
}
则,输出为:
main start
[GC (System.gc()) [PSYoungGen: 1740K->504K(2560K)] 1740K->1592K(9728K), 0.0018813 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 504K->0K(2560K)] [ParOldGen: 1088K->1525K(7168K)] 1592K->1525K(9728K), [Metaspace: 2733K->2733K(1056768K)], 0.0100402 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
main continue
可以看出,实际上在调用了gc 后,gcTest 引用所指向的对象并没有被释放,因为堆的使用大小并没有减去这个对象所占的内存。(被移动到老年代了???)
在 调用gc 前,执行以下操作, 即为对象解除引用:
gcTest = null;
再执行,则输出为:
main start
[GC (System.gc()) [PSYoungGen: 1740K->488K(2560K)] 1740K->580K(9728K), 0.0010038 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 488K->0K(2560K)] [ParOldGen: 92K->525K(7168K)] 580K->525K(9728K), [Metaspace: 2733K->2733K(1056768K)], 0.0055767 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
main continue
这个时候可以看到,在新生代垃圾回收的时候,已经释放了gcTest 之前指向的对象所占用的内存空间。