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 试图删除哪些文件。
我有一个 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 试图删除哪些文件。