`
chenjingbo
  • 浏览: 460663 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

<JVM高级特性与最佳实践> 笔记--一次对象自我拯救的 演示

 
阅读更多

说明,是拜读 <JVM高级特性与最佳实践> 以后的笔记而已,基本上只是做一个记录..

package com.taobao.jvm;

public class FinalizeEscape {
	
	public static FinalizeEscape FC = null;

	@Override
	protected void finalize() throws Throwable {
		super.finalize();
		System.out.println("finalize method invoke");
		FC = this;
	}
	
	public static void main(String[] args) throws Exception {
		FC = new FinalizeEscape();
		
		FC = null;
		System.gc();
		Thread.sleep(500);
		if(FC != null)
			System.out.println("i am alive");
		else 
			System.out.println("i am dead");
		
		FC = null;
		System.gc();
		Thread.sleep(500);
		if(FC != null)
			System.out.println("i am alive");
		else 
			System.out.println("i am dead");
	}
}

 

 

执行的结果是

console输出 写道
finalize method invoke
i am alive
i am dead

 

 

解释:

1 很多教科书上说判断对象是否存活的算法是这样的:给对象添加一个引用计数器,当又一个地方引用他是,计数器+1.引用失效时,则-1.引用为0则回收..但是,其实这种引用计数算法并没有被JAVA采用..JAVA采用的是根搜索算法.

2 jvm在执行垃圾回收的时候会有两个步骤

(1)如果对象没有被引用,则进行第一次标记,然后还做另外一个操作,判断是否需要执行该对象的finalize方法.判断的条件是:该对象有没重写finalize方法.如果没有被重写,则不执行.如果该对象重写了finalize方法,但是已经被虚拟机调用过一次,则也不执行

如果该对象需要被执行finalize方法,则会被放入到一个低优先级队列中,虚拟机会自动开一个线程去执行这个队列.这也是为什么上面在system.gc后还要sleep 500毫秒的原因.

(2)GC会对在队列中对象记性二次标记,如果对象没有在finalize方法中拯救自己,则离死不远了.

3 有些人会怀疑

System.gc();

 

这个方法调用JVM的GC不保证一定能执行GC.这个我通过打印GC信息得到验证,至少在这个程序中,gc是保证被执行的.

[GC 317K->224K(60864K), 0.0006300 secs]
[Full GC 224K->158K(60864K), 0.0040963 secs]
finalize method invoke
i am alive
[GC 793K->190K(60864K), 0.0001947 secs]
[Full GC 190K->158K(60864K), 0.0048994 secs]
i am dead

 

4 作者说:finalize方法是JAVA刚诞生的时候对C/C++的一种妥协.所以,忘掉他吧..虽然他能给对象一个最后拯救自己的机会.

分享到:
评论
1 楼 IcyFenix 2011-07-11  
引用
这个方法调用JVM的GC不保证一定能执行GC

在HotSpot中,调用了System.gc()而不发生GC只有一种情况:设置了-XX:+DisableExplicitGC参数,除此之外,System.gc()是一定能保证触发GC执行的。这个可以通过HotSpot的源码来证明。

相关推荐

Global site tag (gtag.js) - Google Analytics