如果有一个无限循环会出现什么终结器线程做或的Java死锁 finalize方法。如果在Java中的无限循环或僵局究竟会终结器线程做finalize方法
回答
该规范中写道:为对象的存储是由垃圾回收器回收
之前,Java虚拟机将调用该对象的终结。
Java编程语言没有指定终结器将被调用的时间,除非说它将在对象的存储重用之前发生。
我读到这意味着终结器必须已经完成,然后可以重新使用存储。
Java编程语言没有指定哪个线程将为任何给定的对象调用终结器。
地注意到,许多终结线程可以是活动的(这有时需要在大的共享存储器多处理器)是很重要的,并且,如果一个大的连接的数据结构变得垃圾,所有的最终化方法中,每一个对象数据结构可以同时调用,每个终结器调用运行在不同的线程中。
也就是说,终止可能发生在垃圾回收器线程中,在一个单独的thead中,甚至是一个单独的线程池中。不允许JVM中止执行终结器,并且只能使用有限数量的线程(线程是操作系统资源,操作系统不支持任意多的线程)。非终止终结器因此将不得不饿死该线程池,从而禁止收集任何可终结对象,并导致内存泄漏。
下面的测试程序证实了这一行为:
public class Test {
byte[] memoryHog = new byte[1024 * 1024];
@Override
protected void finalize() throws Throwable {
System.out.println("Finalizing " + this + " in thread " + Thread.currentThread());
for (;;);
}
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
new Test();
}
}
}
在甲骨文JDK 7,这个打印:
Finalizing [email protected] in thread Thread[Finalizer,8,system] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at tools.Test.<init>(Test.java:5) at tools.Test.main(Test.java:15)
+1,做了或多或少的相同的测试,并得到了相同的结果。只涉及一个终结器线程。 –
@ mriton,** _的含义是什么?注意许多终结器线程可能是活动的(这在大型共享内存多处理器上有时需要)_ **。它与我们选择的GC算法有什么联系,如CMS。而且,Finalizer线程的数量和GC算法之间是否存在关系? – andy
但是JVM可能会这样做,但不同的JVM可能会以不同的方式执行此操作。如果您对特定的JVM感兴趣,请检查其文档(或更可能是其源代码)。 lpipiora的anwer似乎表明Oracle JVM中总是有一个终结器线程,而不管正在使用的垃圾收集算法。 – meriton
我要说的是,因为Java规范不告诉如何调用finalize方法(只需在对象被垃圾收集之前调用它),该行为就是特定于实现的。
该规范不排除其运行过程中的多个线程,但并不需要它:
地注意到,许多终结的线程可以是活动是很重要的 (这有时需要在大型共享内存多处理器)和 ,如果一个大的连接数据结构变成垃圾,那么所有的数据结构中的每个对象的finalize方法可以同时调用 ,每个终结器调用运行在不同的线程中。
望着JDK7的人士透露,FinalizerThread
保持预定定稿对象的队列(实际上对象由GC添加到队列中,证明当不可达 - 检查ReferenceQueue
DOC):
private static class FinalizerThread extends Thread {
private volatile boolean running;
FinalizerThread(ThreadGroup g) {
super(g, "Finalizer");
}
public void run() {
if (running)
return;
running = true;
for (;;) {
try {
Finalizer f = (Finalizer)queue.remove();
f.runFinalizer();
} catch (InterruptedException x) {
continue;
}
}
}
}
将每个对象从队列中移除,并对其运行runFinalizer
方法。如果在对象上运行完成,并且如果没有运行,则检查完成,作为对本机方法invokeFinalizeMethod
的调用。这个方法简单地调用该对象的finalize
方法:
JNIEXPORT void JNICALL
Java_java_lang_ref_Finalizer_invokeFinalizeMethod(JNIEnv *env, jclass clazz,
jobject ob)
{
jclass cls;
jmethodID mid;
cls = (*env)->GetObjectClass(env, ob);
if (cls == NULL) return;
mid = (*env)->GetMethodID(env, cls, "finalize", "()V");
if (mid == NULL) return;
(*env)->CallVoidMethod(env, ob, mid);
}
这应该导致一种情况,其中的对象列表中得到排队,而FinalizerThread
被阻止故障的对象,这反过来应该导致上到OutOfMemoryError
。
所以要回答原来的问题:
究竟会终结器线程做,如果有在Java中的无限循环或死锁finalize方法。
它会简单地坐在那里并运行该无限循环,直到OutOfMemoryError
。
public class FinalizeLoop {
public static void main(String[] args) {
Thread thread = new Thread() {
@Override
public void run() {
for (;;) {
new FinalizeLoop();
}
}
};
thread.setDaemon(true);
thread.start();
while (true);
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("Finalize called");
while (true);
}
}
注意“定名为”如果在JDK6和JDK7只打印一次。
对象不会被“释放”,也就是说内存将不会被回收,而且在finalize方法中释放的资源将始终保留。
基本上有一个队列包含所有等待finalize()方法执行的对象。终结器线程从此队列中拾取对象 - 运行finalize - 并释放该对象。
如果此线程死锁,则ReferenceQueue队列将长大,并且在某些时候,OOM错误将变得不可避免。此外,资源将被此队列中的对象占用。希望这可以帮助!!
for(;;)
{
Finalizer f = java.lang.ref.Finalizer.ReferenceQueue.remove();
f.get().finalize();
}
- 1. 究竟Java在做什么线程池?
- 2. 究竟做线程的优先级做在Java中
- 3. 如何终止无限循环(线程)
- 4. Java:线程无限循环
- 5. Java中的UDP线程无限循环
- 6. 无限循环或提前终止做while循环
- 7. Java - 终止无限循环
- 8. 如何衡量多久线程究竟会从新拿在java中结束
- 9. 在Java中File.canExecute()究竟做了什么?
- 10. 终结卡在无限循环
- 11. Initialize Component方法究竟做了什么?
- 12. 究竟是什么ClientRuntimeContext.Load方法做
- 13. 无限循环多线程
- 14. 如何做无限循环
- 15. 无限循环在Java中
- 16. for循环造成僵局
- 17. Python:无限循环中的多线程
- 18. 究竟做(:ID)做Product.all.map(:ID)
- 19. 无法从此查询获取结果。我究竟做错了什么?
- 20. 为什么Java toString()会在间接循环中无限循环?
- 21. 在函数式编程中究竟是'怎么做,怎么做'或'关注结果,而不是步骤'
- 22. Java中的无限循环
- 23. Java类Eventqueue究竟做了什么?
- 24. 程序终止后无限循环
- 25. 这个方法究竟做什么? addActionListener方法
- 26. Newton Raphson方法中的无限循环
- 27. 无限循环Java
- 28. 无限循环java
- 29. Java无限循环
- 30. java工作线程中的无限循环违反ScheduledExecutorService暂停
您可以与我们分享您在尝试此操作时观察到的任何行为吗? –
很难观察到这一点,JVM甚至不保证会调用'finalize',针头会说你不知道它什么时候会被叫做 – morgano
@morgano一个简单的'println'就够了。我很久以前玩过这个游戏,“敲定”很快得到调用。只有极少数情况下,在系统关闭之前,某些不可访问的对象没有完成。 –