Java 进程卡在正在删除文件的 SIGTERM 处理程序中

Java process stuck in SIGTERM handler deleting a file

我有一个 java 进程无法响应 SIGTERM。这是一个偶发问题,但同时在多个服务器上发生。我知道我可以用 SIGKILL 杀死它,但想了解为什么它可能会卡住而不响应已发送给它的 SIGTERM 信号。查看 jstack 的输出,似乎以下线程被卡住了:

"SIGTERM handler" daemon prio=10 tid=0x00007fcb30006000 nid=0x259c waiting for monitor entry [0x00007fc98cd2c000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at java.lang.Shutdown.exit(Shutdown.java:212)
        - waiting to lock <0x00000005fc7cdc60> (a java.lang.Class for java.lang.Shutdown)
        at java.lang.Terminator.handle(Terminator.java:52)
        at sun.misc.Signal.run(Signal.java:212)
        at java.lang.Thread.run(Thread.java:745)

"SIGTERM handler" daemon prio=10 tid=0x00007fcb30005000 nid=0x30cb waiting for monitor entry [0x00007fc982282000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at java.lang.Shutdown.exit(Shutdown.java:212)
        - waiting to lock <0x00000005fc7cdc60> (a java.lang.Class for java.lang.Shutdown)
        at java.lang.Terminator.handle(Terminator.java:52)
        at sun.misc.Signal.run(Signal.java:212)
        at java.lang.Thread.run(Thread.java:745)

"SIGTERM handler" daemon prio=10 tid=0x00007fcb30004000 nid=0x1305 waiting for monitor entry [0x00007fc982a8a000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at java.lang.Shutdown.exit(Shutdown.java:212)
        - waiting to lock <0x00000005fc7cdc60> (a java.lang.Class for java.lang.Shutdown)
        at java.lang.Terminator.handle(Terminator.java:52)
        at sun.misc.Signal.run(Signal.java:212)
        at java.lang.Thread.run(Thread.java:745)

"SIGTERM handler" daemon prio=10 tid=0x00007fcb30003000 nid=0xa3e runnable [0x00007fc982585000]
   java.lang.Thread.State: RUNNABLE
        at java.io.UnixFileSystem.delete0(Native Method)
        at java.io.UnixFileSystem.delete(UnixFileSystem.java:265)
        at java.io.File.delete(File.java:1035)
        at java.io.DeleteOnExitHook.runHooks(DeleteOnExitHook.java:80)
        at java.io.DeleteOnExitHook.run(DeleteOnExitHook.java:49)
        at java.lang.Shutdown.runHooks(Shutdown.java:123)
        at java.lang.Shutdown.sequence(Shutdown.java:167)
        at java.lang.Shutdown.exit(Shutdown.java:212)
        - locked <0x00000005fc7cdc60> (a java.lang.Class for java.lang.Shutdown)
        at java.lang.Terminator.handle(Terminator.java:52)
        at sun.misc.Signal.run(Signal.java:212)
        at java.lang.Thread.run(Thread.java:745)

还有很多其他线程,但它们看起来没有什么不寻常的。持有锁的线程似乎正在删除一些文件。有谁知道这个文件可能是什么以及为什么删除它可能会卡住?

它正在删除一个在 JVM 终止时标记为删除的文件 File.deleteOnExit。这可能是您的代码或您创建的库的临时文件。我不清楚为什么这可能会挂起。也许该文件位于非常慢的文件系统(远程文件系统)上,或者某些 I/O 设备已损坏?

如果您在代码中寻找 deleteOnExit 的调用者时没有找到可能的候选者,找出这是哪个文件可能会很复杂。

您可以在 JVM 的打开文件列表中检查可能的候选人(使用 lsof),但该文件当前可能未打开。

可能最好的办法是在发送 SIGTERM 之前用 strace -e unlink,unlinkat -p <PID>strace 附加到您的 JVM,并检查 JVM 试图删除哪些文件。