2010-11-18 6 views
2

Ich habe eine Java-JAR-Datei, die ich von der Windows-Eingabeaufforderung ausführen. Der Code endet normal (d. H. Tut was er soll), aber der Java-Prozess läuft weiter. Die Anwendung ist single-threaded. Ich muss Ctrl-c drücken, um den Prozess nach Abschluss des Codes zu stoppen, um die Eingabeaufforderung zurückzuerhalten.Was hält Java-Prozesse nach der JAR-Ausführung am Leben?

Ich nehme an, dass ich am Ende meiner Hauptmethode eine System.exit(0) setzen könnte, die vermutlich dies beheben würde, aber ich hatte den Eindruck, dass es nicht notwendig war. Unter welchen Bedingungen werden Java-Prozesse am Ende der Ausführung am Leben erhalten? Hier ist die Schale meiner Hauptmethode:

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

Wo der Logger meine eigene unglaublich statische Klasse, die nur Nachrichten an System.out.println() Dumps. "Jetzt beendet" wird in der Konsole angezeigt, der Prozess wird jedoch fortgesetzt. Irgendwelche Ideen?

EDIT: Wie gewünscht, hier das in seiner ganzen Pracht Logger Code ist (ich dich nicht gewarnt :)

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

EDIT EDIT: Ich habe eine endlich auf meinen Versuch hindern, die oben mit dem Thread-Dump-Code Link in Instanz von Toms Antwort. Hier ist der Ausgang:

... [2010.11.18 11:22:57] Ausgabe abgeschlossen. Die gesamte Verarbeitung ist jetzt abgeschlossen.


Thema Name: Referenz Handler java.lang.Object.wait (native Methode) java.lang.Object.wait (Object.java:485) java.lang.ref.Reference $ ReferenceHandler. run (Reference.java:116)


Thema Name: Finalizer java.lang.Object.wait (native Methode) 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)


Thema Name: Signal Dispatcher


Thema Name: Bringen Sie Listener


Name des Threads: Java2D Disposer java.lang.Object.wait (Systemeigene Methode) 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)


Thema Name: Haupt java.lang.Thread.getStackTrace (Thread.java:1436) com.my.code.WorkloadManager.visit (WorkloadManager.java:124) com.my.code.WorkloadManager.visit (Workload Manager. Java: 138) com.my.code.WorkloadManager.main (WorkloadManager.java:71) sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Methode) 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)


Thema Name: com.google.inject.internal.Finalizer java.lang.Object.wait (native Methode) 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)


Thema Name: AWT-Windows- sun.awt.windows.WToolkit.eventLoop (native Methode) sun.awt.windows.WToolkit.run (WToolkit.java:291) java.lang.Thread .run (Thread.java:619)


Thema Name: EventQueueMonitor-ComponentEvtDispatch java.lang.Object.wait (native Methode) java.lang.Object.wait (Object.java:485) com.sun.java.accessibility.util.ComponentEvtDispatchThread.run (EventQueueMonitor.java:616) * ** * ** * ** * ** * ** * Thema Name: Referenz Handler java.lang.Object.wait (native Methode) java .lang.Object.wait (Object.java:485) java.lang.ref.Reference $ ReferenceHandler.run (Reference.java:116)


Thema Name: Finalizer java.lang.Object.wait (Native Methode) 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)


Thema Name: Signal Dispatcher


Thema Name: Bringen Sie Listener


Thema Name: Java2D Disposer java.lang.Object.wait (native Methode) 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)


Thema Name: Haupt 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 Methode) 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)


Thema Name: com.google.inject.internal.Finalizer java.lang.Object.wait (Systemeigene Methode) 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)


Thema Name: AWT-Windows- sun.awt.windows.WToolkit.eventLoop (native Methode) sun.awt.windows.WToolkit.run (WToolkit.java:291) java.lang.Thread.run (Thread.java:619)


Thread-Name: EventQueueMonitor-ComponentEvtDispatch java.lang.Object.wait (systemeigene Methode) java.lang.Object.wait (Object.java:485) com.sun.java.accessibility.util.ComponentEvtDispatchThread.run (EventQueueMonitor.java:616)

+0

Ruft das Java-Programm Runtime.exec() überhaupt auf? – izb

+3

Ich würde vielleicht auch den Logger-Code veröffentlichen. Irgendwie muss ein verwaister Thread bestehen bleiben. Ich kenne keine andere Möglichkeit, dies zu tun. – aepryus

+0

Eine häufige Ursache sind zusätzliche Nicht-Daemon-Threads. Obwohl Ihr Code single-threaded ist, sind Sie sicher, dass keines der Dinge, die Sie aufrufen, Nicht-Daemon-Threads erstellt? –

Antwort

4

Java-Anwendungen mit einem UI-Start-Event, das Threads behandelt, die keine Daemon-Threads sind. Das heißt, das Programm wird nicht beendet, solange diese Threads — ausgeführt werden, auch wenn momentan keine Fenster angezeigt werden.

Haben Sie einen "Exit" -Befehl in Ihrem Menü? Sein Action sollte System.exit(0) aufrufen.

+0

gute Idee, aber das ist keine GUI-Anwendung –

+2

@Chris Knight - Ihre Thread-Dump zeigt, dass es AWT-Ereignis-Threads ausgeführt werden. Es ist möglich, dass eine von Ihnen verwendete Bibliothek das Grafik-Toolkit verwendet. Zum Beispiel habe ich versucht, eine SVG-Bibliothek Server-Seite zu verwenden, um Bilder für eine Web-App zu generieren, aber die App wird nicht auf Google App-Engine ausgeführt, da es AWT-Bibliotheken intern benötigt. – erickson

+0

guter Punkt. Das hatte ich nicht bedacht. Ich benutze JFreeChart-Bibliotheken, um Grafiken zu erstellen, die anschließend auf die Festplatte ausgegeben werden, also keine Benutzeroberfläche, sondern Grafikbibliotheken, die hinter den Kulissen involviert sind. Klingt wie das ist es? –

2

Wenn alles in Ihrem Code scheint normal ist es wahrscheinlich, dass ein verwaister Thread noch läuft.

Der Code here beschreibt, wie alle Fäden in der JVM

Alternativ könnten Sie einen Profiler oder IDE mit eingebautem in Profiler läuft derzeit zur Liste der laufenden Threads anzuzeigen.

Es würde helfen, diese Frage zu beantworten, wenn Sie uns wissen lassen könnten, welche Threads noch laufen, wenn Ihr Code fertig ist; Auch wenn Ihr Code Gewinde es wahrscheinlich immer noch Single sein kann, werden andere Threads in der JVM wie der Garbage-Collection-Thread ausgeführt werden (Obwohl gewohnt GC-Threads die JVM stoppen Verlassen)

+0

Thread-Dump zu meiner Frage hinzugefügt, basierend auf dem Code in Ihrem Link als letzte ausführbare Code in meiner Hauptmethode. –

2

Ein Java-Prozess wird am Leben bleiben so lange da es einen oder mehrere Nicht-Daemon-Threads ausführt.

Erwägen Sie die Verwendung von JVisualVM im Verzeichnis bin des Java-JDK und binden Sie es an Ihr Java-Programm an. Dort können Sie eine Analyse von aktiven Threads und deren Status durchführen sowie einen Thread-Dump ausführen.

2

Basierend auf Ihrem Thread-Dump sieht es so aus, als ob eine der Google-Bibliotheken (vielleicht Guice oder Guava) geladen wird.

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) 

Wenn ja, dann könnte dieser Fehler das Problem verursachen:

Es ist im Zusammenhang mit der Finalizerthread let nicht richtig sein gehen. Es gibt verschiedene Problemumgehungen.

+0

dies könnte auch der Grund sein (siehe Erickson Beitrag oben und verwandte Kommentare), wie ich Guice für die Abhängigkeitsinjektion verwenden. Vielen Dank. –

Verwandte Themen