如果有一個無限循環會出現什麼終結器線程做或的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'就夠了。我很久以前玩過這個遊戲,「敲定」很快得到調用。只有極少數情況下,在系統關閉之前,某些不可訪問的對象沒有完成。 –