在 java 中,如果没有指向 x 的强引用并且 x 有资格进行垃圾收集,那么垃圾收集将在对象 x 上调用 finalize 方法。如果 finalize 方法永远不会终止,这会导致内存泄漏吗?
公共课 X{ 受保护的无效finalize(){ 而(真){} } }
在 java 中,如果没有指向 x 的强引用并且 x 有资格进行垃圾收集,那么垃圾收集将在对象 x 上调用 finalize 方法。如果 finalize 方法永远不会终止,这会导致内存泄漏吗?
公共课 X{ 受保护的无效finalize(){ 而(真){} } }
是的,很容易测试
public class X {
protected void finalize() {
while (true) {
}
}
public static void main(String[] args) throws Exception {
while (true) {
new X();
}
}
}
过了一段时间我得到了
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"
当我删除 finalize() 时,测试从未停止过。请注意,在 JVM 进入 OOM 之前需要一段时间
顺便说一句,运行这个测试就足够了
public class X {
byte[] a = new byte[100 * 1000 * 1000];
protected void finalize() {
System.out.println();
}
public static void main(String[] args) throws Exception {
while (true) {
new X();
}
}
}
打破GC
Exception in thread "main"
java.lang.OutOfMemoryError: Java heap space
at test.X.<init>(X.java:5)
at test.X.main(X.java:13)
注释掉 //System.out.println(); 它不停地工作
是的。
同样在 finalize 方法中,如果您对调用 finalize 方法的对象提供有效引用,Java 不会垃圾收集该对象,也不会再次调用 finalize 方法,因为它只被调用一次。
绝对。内存将在 finalize 方法返回后被释放。如果你的 finalize 永远不会返回,moory 将不会被释放。
谷歌关于垃圾回收中的复活,你会得到 finalize 方法不能保证 gc 的各种实例
它会阻塞 java.lang.ref.Finalizer$FinalizerThread (The Secret Life Of The Finalizer),所有实现 finalize 方法的类的实例都会被阻塞在 java.lang.ref.Finalizer.ReferenceQueue 中。您继续使用“finalize”创建新对象,那些等待执行 finalize 的对象将耗尽内存。如果进行堆转储,您会看到 java.lang.ref.Finalizer 保留了对象,请参见下面的示例(这是一个真实案例)。