【发布时间】:2011-05-12 08:02:31
【问题描述】:
我有一个从 Windows 命令提示符执行的 java jar 文件。代码正常完成(即按预期执行),但 java 进程继续运行。该应用程序是单线程的。代码完成后,我需要按 Ctrl-c 停止该过程以返回命令提示符。
我认为我可以在我的主要方法的末尾放置一个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;
}
}
编辑编辑:我在上面的 try 中放置了一个 finally 块,并使用 instanceofTom 答案中链接中的线程转储代码。这是输出:
... [2010.11.18 11:22:57] 输出完成。所有处理现已完成。
线程名称:引用处理程序 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 Disposer 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 Disposer 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程序是否调用了Runtime.exec()?
-
我可能也会发布记录器代码。不知何故,一个孤立的线程必须持续存在。我知道没有其他方法可以发生这种情况。
-
一个常见的原因是额外的非守护线程。尽管您的代码是单线程的,但您确定您调用的所有东西都没有创建非守护线程吗?
-
我同意以前的 cmets。您可以尝试生成线程转储或使用“jps”工具。
-
@izb - 没有调用 Runtime.exec()。