2010-11-18 8 views
2

私はWindowsのコマンドプロンプトから実行しているjava jarファイルを持っています。コードは正常に終了する(すなわち、それが想定される)が、Javaプロセスは引き続き実行されます。アプリケーションはシングルスレッドです。コマンドプロンプトを返すためにコードが完了した後にプロセスを停止するには、Ctrl-cを押す必要があります。jar実行後にJavaプロセスを生き残らせるには?

System.exit(0)を私の主な方法の最後に置くことができたと思われますが、これはおそらくこれを修正するでしょうが、私はそれが必要ではないという印象を受けました。 Javaプロセスは実行の最後にどのような条件下で生き残ったのですか?ロガーはちょうどSystem.out.println()にメッセージをダンプし、私自身、信じられないほどの基本的な静的なクラスがある

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

:ここに私のメインメソッドのシェルです。 「完了しました」がコンソールに表示されますが、プロセスは引き続き実行されます。何か案は?

EDIT:要求されたとして、ここロガーコードはそのすべての栄光であります(私はあなたに警告しなかった:)

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; 
    } 
} 

編集編集:私は最終的にからのスレッドダンプコードで上記の私の挑戦にブロック置きます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ディスポーザー java.lang.Object.wait(ネイティブメソッド) 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(ネイティブメソッド) 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-Windowsの 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。 ref.Finalizer $ FinalizerThread.run(Finalizer.java:159)


スレッド名:信号ディスパッチャ


スレッド名:アタッチリスナー


スレッド名:Java2Dディスポーザー java.lang.Object.wait(ネイティブメソッド) 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(ネイティブメソッド) 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-Windowsの 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)

+0

JavaプログラムはRuntime.exec()をまったく呼び出しますか? – izb

+3

私はおそらくロガーコードも掲示します。何とか孤立したスレッドが永続している必要があります。私はこれが起こる他の方法がないことを知っています。 – aepryus

+0

頻繁な原因は、デーモンではない追加のスレッドです。あなたのコードはシングルスレッドではありますが、あなたが呼んでいるもののどれも非デーモンスレッドを作成しているとは思わないでしょうか? –

答えて

4

「デーモン」スレッドではないスレッドを処理するUI開始イベントを持つJavaアプリケーション。つまり、現在ウィンドウが表示されていなくても、これらのスレッドが実行中であれば、プログラムは終了しません。—

メニューに[終了]コマンドがありますか? ActionSystem.exit(0)を呼び出す必要があります。

+0

良いアイデアですが、これはGUIアプリケーションではありません –

+2

@Chris Knight - あなたのスレッドダンプは、AWTイベントスレッドが実行中であることを示しています。使用しているライブラリによっては、グラフィックスツールキットが使用されている可能性があります。たとえば、Webアプリケーション用の画像を生成するためにSVGライブラリをサーバー側で使用しようとしましたが、内部的にAWTライブラリが必要なため、アプリケーションはGoogleのアプリケーションエンジン上では実行されません。 – erickson

+0

良い点。私はそれを考慮しなかった。私はJFreeChartライブラリを使ってグラフを生成し、その後ディスクに出力しますので、UIはありませんが、グラフィックライブラリーはバックグラウンドに含まれています。これのような音ですか? –

2

あなたのコード内のすべてが通常と思われる場合、それは可能性があります孤立したスレッドがまだ実行中であることを示します。

コードhereは現在、別の方法として、実行中のスレッドを表示する組み込みのプロファイラと、プロファイラまたはIDEを使用することができますJVM

で実行中のスレッドのすべてを一覧表示する方法について説明します。

コードが完成したときにまだ実行中のスレッドがわかっている場合は、この質問に答えるのに役立ちます。あなたのコードはシングルスレッドかもしれにもかかわらず

+0

あなたのリンクのコードに基づいて私の質問にスレッドダンプが追加され、私のメインメソッドの最後の実行可能コードになりました。 –

2

A Javaプロセスは、そう長く生きているままになります(GCスレッドが文句を言わないから出るのJVMを停止しますが)そう、まだ、このようなガベージコレクションのスレッドとしてJVMで実行されている他のスレッドがあるでしょう1つ以上の非デーモンスレッドが実行されているためです。

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の記事と関連するコメントを参照してください)。ありがとう。 –

関連する問題