JVM便秘攻略二

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wydyd110/article/details/86016465

接上一篇《JVM便秘攻略一》

4 对象已死吗?

堆里存放着Java世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,要确定哪些对象还活着,哪些已经死了。

4.1 引用计数算法

给对象加一个引用计数器,每当有一个地方引用它时,计数器值就+1,;

当引用失效时,计数器值就-1;

任何时候计数器为0的对象就是不可能被使用的。

例子

public class ReferenceCountingGC {
	
	public Object instance = null;
	
	private static final int _1MB = 1024*1024;
	
	//这个成员属性的唯一意义就是占点内存,以便能在GC日志中看清楚是否被回收过
	private byte[] bigSize = new byte[2 * _1MB];
	
	public static void testGC() {
		ReferenceCountingGC obj1 = new ReferenceCountingGC();
		ReferenceCountingGC obj2 = new ReferenceCountingGC();
		
		//相互引用,计数器各为1
		obj1.instance = obj2;
		obj2.instance = obj1;
		
		obj1 = null;
		obj2 = null;
		
		//结果是JVM并没有因为它们互相引用就不回收了
		//所以JVM不是通过引用计数算法来判断对象是否存活
		System.gc();
		
	}
	
	public static void main(String[] args) {
		testGC();
	}
}

-XX:+PrintGC 输出GC日志
-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息
-XX:+PrintGCDetails 输出GC的详细日志
 -XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,2013-05-04T21:53:59.234+0800)
-Xloggc:../logs/gc.log 日志文件的输出路径

使用eclipse控制台打印GC日志,

控制台输出日志:

[GC (System.gc()) [PSYoungGen: 6092K->616K(38400K)] 6092K->624K(125952K), 0.0011515 secs(回收时间)]
[Full GC (System.gc()) [PSYoungGen: 616K->0K(38400K)] [ParOldGen: 8K->510K(87552K)] 624K->510K(125952K), [Metaspace: 2542K->2542K(1056768K)], 0.0049943 secs]

GC日志说明:
GC打印时间: [垃圾回收类型回收时间: [收集器名称: 年轻代回收前占用大小->年轻代回收后占用大小(年轻代当前容量),
年轻代局部GC时JVM暂停处理的时间] 堆空间GC前占用的空间->堆空间GC后占用的空间(堆空间当前容量)
,GC过程中JVM暂停处理的时间]。
垃圾回收类型:分为GC和Full GC.
GC一般为堆空间某个区发生了垃圾回收,
Full GC基本都是整个堆空间及持久代发生了垃圾回收
PSYoungGen:年轻代(新生代)发生了GC
ParOldGen:老年代发生了GC

PSYoungGen: 6092K(年轻代垃圾回收前的大小)->616K(年轻代垃圾回收以后的大小)(38400K)(年轻代的总大小)

由此可知,JVM并没有因为两个对象相互引用就不回收它们,也从侧面说明JVM不是通过引用计数算法来判断对象是否活着。

4.2 可达性分析算法(根搜索算法)

在Java语言中,可作为GC Roots的对象包括下面几种:

4.3 引用

4.3.1 强引用(Strong Reference)

 

 

4.3.2 软引用

 

 

4.3.3 弱引用

 

 

4.3.4 虚引用


本文学习自

《深入理解java虚拟机》

学堂在线-清华大学-许斌《JAVA程序设计进阶》

猜你喜欢

转载自blog.csdn.net/wydyd110/article/details/86016465