转自 http://ju.outofmemory.cn/entry/74671
本文介绍的是Java里一个内建的概念,Finalizer。你可能对它对数家珍,但也可能从未听闻过,这得看你有没有花时间完整地看过一遍java.lang.Object类了。在java.lang.Object里面就有一个finalize()的方法。这个方法的实现是空的,不过一旦实现了这个方法,就会触发JVM的内部行为,威力和危险并存。
如果JVM发现某个类实现了finalize()方法的话,那么见证奇迹的时刻到了。我们先来创建一个实现了这个非凡的finalize()方法的类,然后看下这种情况下JVM的处理会有什么不同。我们先从一个简单的示例程序开始:
import java.util.concurrent.atomic.AtomicInteger;
class Finalizable {
static AtomicInteger aliveCount = new AtomicInteger(0);
Finalizable() {
aliveCount.incrementAndGet();
}
@Override
protected void finalize() throws Throwable {
Finalizable.aliveCount.decrementAndGet();
}
public static void main(String args[]) {
for (int i = 0;; i++) {
Finalizable f = new Finalizable();
if ((i % 100_000) == 0) {
System.out.format("After creating %d objects, %d are still alive.%n", new Object[] {i, Finalizable.aliveCount.get() });
}
}
}
}
这个程序使用了一个无限循环来创建对象。它同时还用了一个静态变量aliveCount来跟踪一共创建了多少个实例。每创建了一个新对象,计数器会加1,一旦GC完成后调用了finalize()方法,计数器会跟着减1。
你觉得这小段代码的输出结果会是怎样的呢?由于新创建的对象很快就没人引用了,它们马上就可以被GC回收掉。因此你可能会认为这段程序可以不停的运行下去,:
After creating 345,000,000 objects, 0 are still alive.
After creating 345,100,000 objects, 0 are still alive.
After creating 345,200,000 objects, 0 are still alive.
After creating 345,300,000 objects, 0 are still alive.
显然结果并非如此。现实的结果完全不同,在我的Mac OS X的JDK 1.7.0_51上,程序大概在创建了120万个对象后就抛出java.lang.OutOfMemoryError: GC overhead limitt exceeded异常退出了。
After creating 900,000 objects, 791,361 are still alive.
After creating 1,000,000 objects, 875,624 are still alive.
After creating 1,100,000 objects, 959,024 are still alive.
After creating 1,200,000 objects, 1,040,909 are still alive.
Exception in thread "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.0857640 secs] [Times: user=0.22 sys=0.02, real=0.09 secs]
[GC [PSYoungGen: 19440K->2560K(19456K)] 33728K->31392K(62976K), 0.0489700 secs] [Times: user=0.14 sys=0.01, real=0.05 secs]
[GC-- [PSYoungGen: 19456K->19456K(19456K)] 48288K->62976K(62976K), 0.0601190 secs] [Times: user=0.16 sys=0.01, real=0.06 secs]
[Full GC [PSYoungGen: 16896K->14845K(19456K)] [ParOldGen: 43182K->43363K(43520K)] 60078K->58209K(62976K) [PSPermGen: 2567K->2567K(21504K)], 0.4954480 secs] [Times: user=1.76 sys=0.01, real=0.50 secs]
[Full GC [PSYoungGen: 16896K->16820K(19456K)] [ParOldGen: 43361K->43361K(43520K)] 60257K->60181K(62976K) [PSPermGen: 2567K->2567K(21504K)], 0.1379550 secs] [Times: user=0.47 sys=0.01, real=0.14 secs