finalizer java_Java的Finalizer引发的内存溢出

转自 http://ju.outofmemory.cn/entry/74671

本文介绍的是Java里一个内建的概念,Finalizer。你可能对它对数家珍,但也可能从未听闻过,这得看你有没有花时间完整地看过一遍java.lang.Object类了。在java.lang.Object里面就有一个finalize()的方法。这个方法的实现是空的,不过一旦实现了这个方法,就会触发JVM的内部行为,威力和危险并存。

如果JVM发现某个类实现了finalize()方法的话,那么见证奇迹的时刻到了。我们先来创建一个实现了这个非凡的finalize()方法的类,然后看下这种情况下JVM的处理会有什么不同。我们先从一个简单的示例程序开始:

importjava.util.concurrent.atomic.AtomicInteger;classFinalizable{staticAtomicIntegeraliveCount =newAtomicInteger(0);Finalizable(){aliveCount.incrementAndGet();}@Overrideprotectedvoidfinalize()throwsThrowable{Finalizable.aliveCount.decrementAndGet();}publicstaticvoidmain(Stringargs[]){for(inti =0;;i++){Finalizablef =newFinalizable();if((i %100_000)==0){System.out.format("After creating %d objects, %d are still alive.%n",newObject[]{i,Finalizable.aliveCount.get()});}}}}

这个程序使用了一个无限循环来创建对象。它同时还用了一个静态变量aliveCount来跟踪一共创建了多少个实例。每创建了一个新对象,计数器会加1,一旦GC完成后调用了finalize()方法,计数器会跟着减1。

你觉得这小段代码的输出结果会是怎样的呢?由于新创建的对象很快就没人引用了,它们马上就可以被GC回收掉。因此你可能会认为这段程序可以不停的运行下去,:

Aftercreating 345,000,000objects,0are still alive.Aftercreating 345,100,000objects,0are still alive.Aftercreating 345,200,000objects,0are still alive.Aftercreating 345,300,000objects,0are still alive.

显然结果并非如此。现实的结果完全不同,在我的Mac OS X的JDK 1.7.0_51上,程序大概在创建了120万个对象后就抛出java.lang.OutOfMemoryError: GC overhead limitt exceeded异常退出了。

Aftercreating 900,000objects,791,361are still alive.Aftercreating 1,000,000objects,875,624are still alive.Aftercreating 1,100,000objects,959,024are still alive.Aftercreating 1,200,000objects,1,040,909are still alive.Exceptioninthread "main"java.lang.OutOfMemoryError:GC overhead limit exceeded at java.lang.ref.Finalizer.register(Finalizer.java:90)at java.lang.Object.(Object.java:37)at eu.plumbr.demo.Finalizable.(Finalizable.java:8)at eu.plumbr.demo.Finalizable.main(Finalizable.java:19)

垃圾回收的行为

想弄清楚到底发生了什么,你得看下这段程序在运行时的状况如何。我们来打开-XX:+PrintGCDetails选项再运行一次看看:

[GC [PSYoungGen:16896K->2544K(19456K)]16896K->16832K(62976K),0.0857640secs][Times:user=0.22sys=0.02,real=0.09secs][GC [PSYoungGen:19440K->2560K(19456K)]33728K->31392K(62976K),0.0489700secs][Times:user=0.14sys=0.01,real=0.05secs][GC--[PSYoungGen:19456K->19456K(19456K)]48288K->62976K(62976K),0.0601190secs][Times:user=0.16sys=0.01,real=0.06secs][FullGC [PSYoungGen:16896K->14845K(19456K)][ParOldGen:43182K->43363K(43520K)]60078K->58209K(62976K)[PSPermGen:2567K->2567K(21504K)],0.4954480secs][Times:user=1.76sys=0.01,real=0.50secs][FullGC [PSYoungGen:16896K->16820K(19456K)][ParOldGen:43361K->43361K(43520K)]60257K->60181K(62976K)[PSPermGen:2567K->2567K(21504K)],0.1379550secs][Times:user=0.47sys

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值