可复现的 Java 进程卡死,如何排查问题

2021-11-24 11:12:44 +08:00
 nonoyang

场景:有一个单独的服务,用于测试一个大的定时任务(包含大量读写操作),定时任务运行大概 30 分钟后,会出现卡死情况。Java 进程还存在但处于暂停状态。日志停止输出,且没有任何报错。

进程信息: PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 8831 **** 20 0 9781344 2.491g 14912 t 0.0 8.0 23:50.15 java

gc 部分日志: 2021-11-24T09:43:51.293+0800: 58343.178: [GC (Allocation Failure) [PSYoungGen: 1045888K->416K(1047552K)] 1379025K->333593K(2096128K), 0.0061813 secs] [Times: user=0.02 sys=0.01, real=0.01 secs] 2021-11-24T09:44:37.862+0800: 58389.746: [GC (Allocation Failure) [PSYoungGen: 1046944K->288K(1047552K)] 1380121K->333473K(2096128K), 0.0063377 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 2021-11-24T09:45:23.641+0800: 58435.526: [GC (Allocation Failure) [PSYoungGen: 1046816K->387K(1047552K)] 1380001K->333597K(2096128K), 0.0063043 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

卡死后,jmap,jstack 相关指令都无法再执行了。 数据库用的是 oracle 12c,查看还是正常的,所以应该不是数据库的问题。 请问大佬们,现在有啥排查问题的手段吗?

3700 次点击
所在节点    Java
18 条回复
darrh00
2021-11-24 11:22:23 +08:00
什么环境?
如果是 Linux 的话可以试试 kill -QUIT pid
yanweichen0720
2021-11-24 11:25:09 +08:00
启动的时候加上远程监控的参数,然后用 jmc 实时看下具体哪些类炸了
nonoyang
2021-11-24 11:34:06 +08:00
@darrh00 是 linux
huntagain2008
2021-11-24 11:52:06 +08:00
建议追加附言用 markdown 的代码块把进程信息和日志显示的漂亮点。
whx
2021-11-24 12:28:46 +08:00
看起来是内存满了不够用导致的,可以把-Xmx 调大一点试下。
cheng6563
2021-11-24 14:02:45 +08:00
-XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=12345.hprof
加这仨参数,使其发生内存问题时直接退出并留下 dump ,然后分析 dump 就行了。
java 发生 OOM 错误时很容易失控,不退出也往往不能正常工作,还不如直接退掉让守护进程重新拉起来了事。
zxyroy
2021-11-24 15:22:34 +08:00
可以排查下是不是有什么 stream 忘记 close 了
nonoyang
2021-11-24 15:31:42 +08:00
@zxyroy 这个应该是不存在的。这个任务只是循环对一些数据进行相关的查询,并做后续的 insert 。只是数据量很大,并且每个数据要做的对应查询也很多。
nonoyang
2021-11-24 15:33:20 +08:00
@whx 这个之前已经调高过一次了。现在是-Xms2g -Xmx2g -Xmn1g -XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m
nonoyang
2021-11-24 15:35:46 +08:00
@cheng6563 这个我试下。之前是想等挂掉的时候再去拿内存快照,但后来试了两次,发现进程直接无响应了。。。
fengpan567
2021-11-24 16:03:33 +08:00
是不是文件流没关,服务器上 ulimit -n 检查一下打开文件数的限制是多少
ChovyChu
2021-11-24 16:32:43 +08:00
jstat -gc pid 1000 看一下 gc 频率吧,卡住大概率是经常 fgc 了
nonoyang
2021-11-24 16:45:49 +08:00
@ChovyChu 测试了几次,发生了 1 、2 次 full gc ,我不太清楚这个频率是否过高。gc 日志我是有记录的,平均 40s 到 1 分多钟左右执行一次新生代的 gc 。full gc 的记录:

[Full GC (System.gc())
[PSYoungGen: 8519K->0K(958976K)]
[ParOldGen: 83126K->75678K(1048576K)]
91646K->75678K(2007552K),
[Metaspace: 39477K->39477K(1083392K)],
0.4594062 secs]
[Times: user=3.28 sys=0.02, real=0.45 secs]
huang119412
2021-11-24 17:12:23 +08:00
什么都不说,怎么排查,测试机配置和 os 版本,java 版本,框架等。还有系统什么状态?从 Full GC (System.gc())看,这应该回收堆外内存用的。IO 定时任务 CPU 一般占用不会高,最大可能出现在内存和磁盘。我的一个经验是,以前我们测试机用的是机械盘,数据库操作多(随机)的时候,磁盘经常无响应,造成程序假死。
xylxAdai
2021-11-24 17:33:05 +08:00
strace ?
zeni123
2021-11-25 01:03:00 +08:00
应该就是内存用多了吧 ParallelGC STW 太长了。增加或者减少堆内存看看从运行时间卡死会不会变化。

这是 java 几,可以换用 G1 吗,换垃圾回收器解决不了卡死问题,但至少会有响应。至于为什么内存会用多了,可以看看有没有内存泄漏。
nonoyang
2021-11-25 09:20:00 +08:00
@zeni123 java 8,我换下试试。也是怀疑是内存用多了,但总是直接卡死,没办法获取卡死时的内存使用情况。我准备实在不行,运行一段时间后,不等卡死,提前 dump 。
Variazioni
2021-11-25 10:17:29 +08:00
我就遇到过类似的问题。。最后用 jProfiler 查到了原因。。
试用期 10 天。。应该够用了吧。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/817605

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX