Intro
执行
java -jar xxx.jar
时,出现了 java 进程卡住,屏幕上没有任何输出。
Debug 过程
查看系统日志
查看 /var/log/syslog、/var/log/messages,都没有报错信息。
查看 Java 进程自己的输出日志
没有报错。
查看系统级别信息
# 查看进程
ps -ef |grep java
# 查看系统负载,没有消耗过多资源
top
# 查看内存使用情况
free -mh
# 查看端口占据,没有出现端口被占的情况
ss -anp |grep 9600
查看 Java pid 对应的 /proc/[pid]/ 目录内容
以下参考链接:Java程序卡住问题的解决
/proc/pid/cmdline 进程启动命令
/proc/pid/cwd 链接到进程当前工作目录
/proc/pid/environ 进程环境变量列表
/proc/pid/exe 链接到进程的执行命令文件
/proc/pid/fd 包含进程相关的所有的文件描述符
/proc/pid/maps 与进程相关的内存映射信息
/proc/pid/mem 指代进程持有的内存,不可读
/proc/pid/root 链接到进程的根目录
/proc/pid/stat 进程的状态
/proc/pid/statm 进程使用的内存的状态
/proc/pid/status 进程状态信息,比stat/statm更具可读性
/proc/self 链接到当前正在运行的进程
查看 /proc/[pid]/status,没有异常
Name: java
Umask: 0002
State: S (sleeping)
Tgid: 6545
Ngid: 0
Pid: 6545
PPid: 1
TracerPid: 0
Uid: 1001 1001 1001 1001
Gid: 1001 1001 1001 1001
FDSize: 256
Groups: 27 1001
NStgid: 6545
NSpid: 6545
NSpgid: 6545
NSsid: 30676
VmPeak: 5710304 kB
VmSize: 5710304 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 1026260 kB
VmRSS: 1020728 kB
RssAnon: 1002968 kB
RssFile: 17760 kB
RssShmem: 0 kB
VmData: 1364668 kB
VmStk: 132 kB
VmExe: 4 kB
VmLib: 17620 kB
VmPTE: 2488 kB
VmSwap: 0 kB
HugetlbPages: 0 kB
CoreDumping: 0
Threads: 45
SigQ: 0/31804
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 2000000181005ccf
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
NoNewPrivs: 0
Seccomp: 0
Speculation_Store_Bypass: thread vulnerable
Cpus_allowed: f
Cpus_allowed_list: 0-3
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 1
nonvoluntary_ctxt_switches: 0
查看 /proc/[pid]/cwd/,链接了执行目录,看不出特别的。
查看 /proc/[pid]/task/,链接了子进程,看不出异常。
jvm 堆栈信息查看
# 查看 java 进程
jps
# 查看堆内存,用于定位死锁
jstack -l [pid]
也可以使用这个方法查看,参考链接:Java程序卡住问题的解决
kill -3 [pid]
kill命令只能在linux下面用,其实也可以用jdk自带的工具,比如用jstack去查看线程运行情况,这样在windows下面也可以使用。总结:Java是一个很开放的程序,对于出问题的情况利用提供的工具大部分都很容易定位。这中间一是你要知道有什么样的工具可以辅助你,至少你要把jdk/bin下面自带的工具看一遍;另外就是要有借助工具解决问题的意识,如果还是和刚开始学写代码的时候就知道到处打印输出的语句,那解决问题的层次实在是太低了,也很难把问题真正解决。
Java Thread State
以下参考链接: 各种 Java Thread State 第一分析法则
4,如果大量线程在“waiting on condition”:
可能是它们又跑去获取第三方资源,尤其是第三方网络资源,迟迟获取不到Response,导致大量线程进入等待状态。
所以如果你发现有大量的线程都处在 Wait on condition,从线程堆栈看,正等待网络读写,这可能是一个网络瓶颈的征兆,因为网络阻塞导致线程无法执行。
Summary
最终在 jstack 中定位到了卡住的位置,是网卡多 ip 绑定导致的,作相应调整即可。另,引言中定位 Java 的思路值得借鉴。
"spring.cloud.inetutils" #12 daemon prio=5 os_prio=0 tid=0x00007f99a466a000 nid=0x482b waiting on condition [0x00007f998756d000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x0000000083e37c70> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Reference
- 一次完整 debug 的博客参考: 记一次找因redis使用不当导致应用卡死bug的过程