java.exe没有结束-只剩下一个OS线程

java.exe没有结束-只剩下一个OS线程,java,multithreading,terminate,Java,Multithreading,Terminate,调度器启动一个java应用程序,该应用程序在大多数情况下不会出现任何问题 但是,有时候java.exe进程并没有结束。 就我们所见,java应用程序本身已经结束,但是java.exe进程没有结束。 没有解决办法,只有消灭它 Process Explorer仅显示该进程的一个线程(从操作系统的角度来看,不是java)。它包含状态“Wait:WrKeyedEvent”和以下堆栈 ntoskrnl.exe!KeWaitForMultipleObjects+0x0a ntoskrnl.exe!ExfRe

调度器启动一个java应用程序,该应用程序在大多数情况下不会出现任何问题

但是,有时候java.exe进程并没有结束。 就我们所见,java应用程序本身已经结束,但是java.exe进程没有结束。 没有解决办法,只有消灭它

Process Explorer仅显示该进程的一个线程(从操作系统的角度来看,不是java)。它包含状态“Wait:WrKeyedEvent”和以下堆栈

ntoskrnl.exe!KeWaitForMultipleObjects+0x0a
ntoskrnl.exe!ExfReleasePushLock+0x8ec
ntoskrnl.exe!_misaligned_access+0x331
ntdll.dll!ZwReleaseKeyedEvent+0xa
ntdll.dll!RtlFindMostSignificatBit+0xa0
ntdll.dll!RtlProcessFlsData+0xdc
ntdll.dll!LdrShutdownProcess+0xa9
ntdll.dll!RtlExitUserProcess+0x90
msvcrt.dll!wcstoui64+0x2fa
jvm.dll!JVM_Clone
jvm.dll!JVM_Clone
jvm.dll!JVM_Clone
jvm.dll!JVM_Clone
jvm.dll!JVM_Clone
jvm.dll!JVM_FindSignal
msvcrt.dll!srand
msvcrt.dll!ftime64_s
kernel32.dll!BaseThreadInitThunk
ntdll.dll!RtlUserThreadStart
有人知道,为什么java.exe没有结束

编辑关于响应“一个没有deamon线程仍在运行”

问题不在于Java应用程序中的剩余线程。一个Java应用程序有几个正在运行的(Java-)线程,即使其中只有一个是非执事线程

对于关闭钩也是如此。请参见此示例:

/** Main class */
public class TestShutdown
{
    public static void main (final String[] args) throws FileNotFoundException
    {
        Runtime.getRuntime().addShutdownHook(new HookThread());
    }

}

/** The hook Thread */
final class HookThread extends Thread
{

    public HookThread()
    {
        super(HookThread.class.getName();
    }

    @Override
    public void run()
    {
        try
        {
            sleep(5000l);
        } catch (final InterruptedException ex) { throw new Error(); }

        final StringBuilder sb = new StringBuilder();
        Map<Thread, StackTraceElement[]> traces = Thread.getAllStackTraces();
        sb.append("Number of threads: " + traces.size() + "\n");
        for (final Thread th: traces.keySet())
        {
            sb.append("-----------------\n");
            sb.append(th.toString()+"  "+ (th.isDaemon() ? " (deamon) " : " (not deamon) ") + "\n");
            final StackTraceElement[] trace = traces.get(th);
            for (int j=0; j < trace.length; j++)
                sb.append("  at " + trace[j] + "\n");
        }
        System.out.println(sb.toString());
    }

}
(顺便说一句:在本例中,我们有两个not deamons:钩子线程和
DestroyJavaVM
,它已启动钩子并等待它结束。)


而且:我挂起的java.exe只有一个操作系统线程!很明显,程序java.exe必须有更多的线程,因为应用程序正在其虚拟机中运行。。。(在上面的程序中,有6个Java线程在VM中运行,但Java.exe进程本身有17个OS线程。)

您的Java应用程序不会因为其中的某些线程永久循环或对资源有挂起的锁定而结束,这证明了一个错误,您需要联系java应用程序开发人员,向他展示您当前的问题


首先:对于在生产环境中使用的应用程序来说,通常最好有某种形式的看门狗——有几个经过良好测试的库用于这种目的——比如。像这样的类只是挂起/等待,直到超时发生-在这一点上,它们将调用您提供的函数,建议在该函数中调用
System.exit(1)
,有效地强制关闭。这是因为看门狗是一个
守护进程线程,一旦其他所有线程都已“死亡”,它将被杀死,因此如果应用程序在预设的超时内结束,看门狗将永远不会启动。

如果关闭挂钩或终结器未完成,则可能发生这种情况。是否启用了关闭挂钩或Runtime.runFinalizersOnExit


无论如何,如果您是开发人员,您可以启动一个额外的线程来监视其他线程正在做什么。请参阅java安装中可用的(1.6版)jvisualvm,它允许您连接到java进程。尝试选择您的java进程,转到thread选项卡查看哪些线程正在运行,甚至您可以执行线程转储并附加到问题,这会非常有帮助。我已经尝试调试该进程。但这是不可能的。Jstack无法附加到应用程序。这是合乎逻辑的,因为windows进程只有一个线程(而不是几个线程用于“仍在运行”的应用程序)。在我的例子中,java.exe有点像僵尸……我喜欢vmmap程序查看Windows上的进程详细信息,它还显示各个线程使用的内存。也许你会从中发现一些有趣的东西。我不这么认为,因为java.exe进程只有一个OS线程(见上文)。我已经检查了我的代码(我是java应用程序开发人员,知道什么是看门狗。)这似乎是正常的等待条件,而不是死锁。对死锁的共同理解涉及多个实体之间的争用。您是否引用了您认为权威的替代定义?wait=lock=thread suspension=thread yield=NOP。即使看起来是用java编写单线程应用程序,它也不会是单线程的——至少还有一个线程等待主线程终止。几乎所有高级语言都是如此,如果您想避免操作系统特定的多线程,您很可能需要使用较低级别的语言,如C,在C中,您可以轻松地(!)强制您的进程只有一个线程。您可以使用Eclipse、最新的JDK和debug透视图自己进行测试。即使您的应用程序有多个线程,其中一个线程无限期地等待某个条件,但这并不意味着两个(或更多)线程会相互阻塞。请花点时间阅读什么是死锁,然后再批评所有其他开发人员他们所知道的,而不是断言。你基本上只是说相互阻塞的线程不称为死锁。基本上,你重复了我的答案。这没问题,但请再解释一下,因为这显然是必要的。@Specializet您没有写任何关于关闭挂钩、终结器的内容。这可能是应用程序中只有一个线程的原因,而您的回答没有解释这一事实。因此:您的语句无效。@Specializet我的意思是关闭挂钩线程是OP正在观察的单个线程。@Specializet好吧,如果您指的是退出时关闭挂钩/终结器,您应该这样写。但如果你的意思是“正常”线程,那么你的答案肯定是错误的,因为在正常状态下,每个应用程序都有很多线程。只需检查hello world应用程序中的线程数。
Number of threads: 6
-----------------
Thread[Reference Handler,10,system]   (deamon)
  at java.lang.Object.wait(Native Method)
  at java.lang.Object.wait(Unknown Source)
  at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
-----------------
Thread[Finalizer,8,system]   (deamon)
  at java.lang.Object.wait(Native Method)
  at java.lang.ref.ReferenceQueue.remove(Unknown Source)
  at java.lang.ref.ReferenceQueue.remove(Unknown Source)
  at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)
-----------------
Thread[HookThread,5,main]   (not deamon)
  at java.lang.Thread.dumpThreads(Native Method)
  at java.lang.Thread.getAllStackTraces(Unknown Source)
  at HookThread.run(TestShutdown.java:59)
-----------------
Thread[Attach Listener,5,system]   (deamon)
-----------------
Thread[DestroyJavaVM,5,main]   (not deamon)
  at java.lang.Object.wait(Native Method)
  at java.lang.Thread.join(Unknown Source)
  at java.lang.Thread.join(Unknown Source)
  at java.lang.ApplicationShutdownHooks.runHooks(Unknown Source)
  at java.lang.ApplicationShutdownHooks$1.run(Unknown Source)
  at java.lang.Shutdown.runHooks(Unknown Source)
  at java.lang.Shutdown.sequence(Unknown Source)
  at java.lang.Shutdown.shutdown(Unknown Source)
-----------------
Thread[Signal Dispatcher,9,system]   (deamon)