2010-11-18 92 views
2

我有一個java的jar文件,我正在執行從Windows命令提示符。代碼正常完成(即做它應該做的),但java進程繼續運行。該應用程序是單線程的。我需要在代碼完成後按Ctrl-c來停止進程,以便返回命令提示符。在jar執行後,java進程保持活動狀態嗎?

我認爲我可以把System.exit(0)放在我的主要方法的末尾,這可能會解決這個問題,但我的印象是沒有必要。 java進程在執行結束時保持活動的條件是什麼?這是我的主要方法的外殼:

public static void main(String[] args) { 
    try { 
     //application code here 
     Logger.log("Now finished"); 
    } catch (SomeExceptoin e) { 
     Logger.error("Some error occured"); 
    } 
} 

當記錄儀是剛剛轉儲消息System.out.println()我自己的令人難以置信的基本靜態類。 「現在完成」出現在控制檯中,但該過程繼續運行。有任何想法嗎?

編輯:按照要求,這裏是在其所有的榮耀的記錄代碼(我沒提醒你:)

public class Logger { 
    public static void logInfo(String logMessage) 
    { 
     System.out.println(timestamp() + logMessage); 
    } 
    private static String timestamp() 
    { 
     SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd hh:mm:ss"); 
     String timestamp = "[" + formatter.format(new Date()) + "] "; 
     return timestamp; 
    } 
} 

編輯編輯:我把finally塊到我嘗試了上述從線程轉儲代碼鏈接在instanceofTom的答案中。這裏輸出:

... [2010.11.18 11:22:57]輸出完成。所有處理現在完成。


線程名稱:指向處理器 java.lang.Object.wait(本機方法) java.lang.Object.wait(Object.java:485) java.lang.ref.Reference中的$ ReferenceHandler。運行(Reference.java:116)


線程名稱:終結 java.lang.Object.wait(本機方法) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116) 的java .lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132) java.lang.ref.Finalizer $ FinalizerThread.run(Finalizer.java:159)


線程名稱:信號調度


主題名稱:將監聽


線程名稱:Java2D Disposer java.lang.Object.wait(Native Method) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116) java。 lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132) sun.java2d.Disposer.run(Disposer.java:125) java.lang.Thread.run(Thread.java:619)


線程名:main java.lang.Thread.getStackTrace(Thread.java:1436) com.my.code.WorkloadManager.visit(WorkloadManager.java:124) com.my.code.WorkloadManager.visit(WorkloadManager。 java:138) com.my.code.WorkloadManager.main(WorkloadManager.java:71) sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect。NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) java.lang.reflect.Method.invoke(Method.java:597) org.eclipse.jdt.internal .jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:56)


線程名稱:com.google.inject.internal.Finalizer java.lang.Object.wait(本機方法) 的java.lang.ref .ReferenceQueue.remove(ReferenceQueue.java:116) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132) com.google.inject.internal.Finalizer.run(Finalizer.java:114)


主題名稱:AWT窗口 sun.awt.windows.WToolkit.eventLoop(本機方法) sun.awt.windows.WToolkit.run(WToolkit.java:291) 的java.lang.Thread .RUN(Thread.java:619)


主題名稱:EventQueueMonitor-ComponentEvtDispatch java.lang.Object.wait(本機方法) java.lang.Object.wait(Object.java:485) com.sun.java.accessibility.util.ComponentEvtDispatchThread.run(EventQueueMonitor.java:616)* ** * ** * ** * ** * ** * 線程名稱:指向處理器 java.lang.Object.wait(本機方法) 的java .lang.Object.wait(Object.java:485) java.lang.ref.Reference中的$ ReferenceHandler.run(Reference.java:116)


線程名稱:終結 java.lang.Object.wait(本地方法) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132) java.lang.Object ref.Finalizer $ FinalizerThread.run(Finalizer.java:159)


線程名稱:信號調度


主題名稱:將監聽


線程名:Java2D Disposer java.lang.Object.wait(Native Method) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java: 132) sun.java2d.Disposer.run(Disposer.java:125) java.lang.Thread.run(Thread.java:619)


線程名稱:主要 的java.lang.Thread。 getStackTrace(Thread.java:1436) com.my.code.WorkloadManager.visit(WorkloadManager.java:124) com.my.code.WorkloadManager.visit(WorkloadManager.java:138) com.my.code。WorkloadManager.main(WorkloadManager.java:71) sun.reflect.NativeMethodAccessorImpl.invoke0(本機方法) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java: 25) java.lang.reflect.Method.invoke(Method.java:597) org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:56)


主題名稱: com.google.inject.internal.Finalizer java.lang.Object.wait(Native Method) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132) com.google.inject.internal.Finalizer.run(Finalizer.java:114)


主題名稱:AWT窗口 sun.awt.windows.WToolkit.eventLoop(本機方法) sun.awt.windows.WToolkit.run(WToolkit.java:291) java.lang.Thread.run(Thread.java:619)


線程名:EventQueueMonitor-ComponentEvtDispatch java.lang.Object.wait(Native Method) java.lang.Object.wait(Object.java:485) com.sun.java.accessibility.util.ComponentEvtDispatchThread.run(EventQueueMonitor.java:616)

+0

java程序是否調用Runtime.exec()? – izb 2010-11-18 22:25:32

+3

我也許會發布記錄器代碼。不知何故,一個孤兒的線程必須堅持。我知道沒有其他辦法會發生這種情況。 – aepryus 2010-11-18 22:25:58

+0

一個常見的原因是附加的非守護線程。雖然你的代碼是單線程的,但你是否肯定你所調用的內容都不是創建非守護線程? – 2010-11-18 22:30:05

回答

4

使用UI啓動事件處理不是「守護進程」線程的線程的Java應用程序。也就是說,只要這些線程正在運行,程序就不會終止,即使當前沒有窗口顯示,也可以運行—。

你的菜單上是否有「退出」命令?其Action應調用System.exit(0)

+0

好主意,但這不是GUI應用程序 – 2010-11-19 07:39:46

+2

@Chris Knight - 你的線程轉儲顯示有AWT事件線程正在運行。您正在使用的某些庫可能使用圖形工具包。例如,我嘗試使用SVG庫服務器端爲Web應用程序生成圖像,但該應用程序不會在Google應用程序引擎上運行,因爲它需要在內部使用AWT庫。 – erickson 2010-11-19 17:13:40

+0

好點。我沒有考慮過。深入挖掘我正在使用JFreeChart庫來生成隨後得到輸出到磁盤的圖形,所以沒有UI,但圖形庫涉及幕後。聽起來像這樣嗎? – 2010-11-19 22:29:51

2

如果一切都在你的代碼看起來正常,很可能有一個孤兒的線程仍在運行。

代碼here介紹如何列出當前所有的JVM

運行或者你可以使用一個分析器或IDE內置的分析器來查看正在運行的線程線程。

如果您可以讓我們知道您的代碼完成後仍在運行哪些線程,它將有助於回答此問題; 儘管你的代碼可能是單線程的,但仍有可能在JVM中運行其他線程,例如垃圾收集線程(雖然GC線程不會阻止JVM退出)

+0

線程轉儲添加到我的問題根據您的鏈接中的代碼被放在我的主要方法中的最後一個可執行代碼。 – 2010-11-18 23:31:46

2

Java進程將保持活着很長時間因爲它有一個或多個非守護線程正在運行。

考慮使用位於Java JDK的bin目錄中的JVisualVM並將其附加到Java程序中。在那裏您將能夠執行活動線程及其狀態的分析以及執行線程轉儲。

2

根據您的線程轉儲,它看起來像是一個Google庫(可能是Guice或Guava)正在加載。

Thread name: com.google.inject.internal.Finalizer 
java.lang.Object.wait(Native Method) 
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116) 
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132) 
com.google.inject.internal.Finalizer.run(Finalizer.java:114) 

如果是這樣,那麼這個錯誤可能是導致此問題:

它與不被終結器線程放手正確。發佈了各種解決方法。

+0

這也可能是因爲我使用Guice進行依賴注入的原因(請參閱上面的erickson的帖子和相關評論)。謝謝。 – 2010-11-19 22:30:33

相關問題