记录一次Java程序异常退出的排查过程


前言

最近正处于项目开发阶段,前端一直反应服务访问不上,每次重启之后隔不了多长时间就会出现异常退出,通过网上查找各种资料最终解决了异常退出的问题。


一、异常退出信息

Java程序运行在JDK11的本地测试服务器上,服务器的配置都很高,上百G的内存,运行程序之后,有时几分钟或者不到一个小时的时间就会出现异常退出,查看输出日志没有看到异常信息。

二、排查步骤

1.输出dump文件

根据通常的处理方式输出dump文件:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./dump .hprof

但实际情况崩溃的时候没有输出文件

2.排查是否Linux系统主动杀掉了进程

命令如下:

egrep -i 'killed process' /var/log/messages

如果搜索出了Out of memory相关的日志,则基本可以确定是机器内存不足。


当然,你也可以去内核日志里头查询。有时Linux系统或者系统上运行的java或者其它进程,会发生一些莫名其妙的问题,比如突然挂掉了,比如突然重启等等。在软件上找不到问题所在,此时我们应该怀疑硬件或者内核的问题,此时我们就可以使用 dmesg来查看:

dmesg | grep java

输出如下 :

[5673702.665338] Out of memory: Kill process 29953 (java) score 431 or sacrifice child[5673702.665338] Killed process 29953, UID 500, (java) total-vm:9805316kB, anon-rss:2344496kB, file-rss:128kB

如果出现上面的情况,可以确定是系统kill掉了进程。

3.JVM自身奔溃

JVM自身故障导致进程没有时,会有一个hs_err_pid_xxx.log的文件生成,它包含了导致crash的重要信息,通过分析文件来查找crash原因。
该文件的目录,默认是在工作目录下,同样也可以通过Java启动参数来设置:

-XX:ErrorFile=/var/log/hs_err_pid.log

如果拿到这个文件后,详细分析日志里面的内容。

4.JVM参数调整

我们可以在启动参数上添加以下命令通过jvisualvm直观的查看JVM、线程的实时运行情况:

-Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.128.250

通过实时的JVM状态发现,程序的堆空间没有配置,使用的JVM默认的堆空间大小,通过调整JVM参数观察一段时间程序没有出现异常退出的情况。

-Xms8g -Xmx8g -Xmn2g -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=512m 

当然上面参数的值需要根据自己的实际情况进行调整。

总结

通过JDK自带的jstat工具,日常观察JVM的对象创建速度、YGC次数、YGC频率、YGC耗时,YGC后有多少对象进入OLD区,FGC次数,FGC频率、FGC耗时、GC总耗时,可以初步看出程序的内存使用情况,再结合上面的一些方式基本可以排查出异常退出的原因。

附:G1常用的JVM参数

#堆内存最大最小值为4g,新生代内存2g
-Xms4g -Xmx4g -Xmn2g 
#元空间128m,最大320m
-XX:MetaspaceSize=128m 
-XX:MaxMetaspaceSize=320m 
#开启远程debug
-Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n 

#使用G1垃圾收集器,在低延迟和高吞吐间寻找平衡,可以调整最大停止时间,设置新生代大小来提高吞吐量,让出cpu资源
-XX:+UseG1GC
#设置最大暂停时间,默认200ms
-XX:MaxGCPauseMillis=200
#指定Region大小,必须是2次幂
-XX:G1HeapRegionSize=2m
#反复执行混合回收8次,每次回收受MaxGCPauseMillis的影响可能一次性回收不了所有垃圾,增加次数才能回收的更彻底
-XX:G1MixedGCCountTarget=8
# 混合回收整理出来的空闲空间占heap的10时,结果老年代的回收,默认5
-XX:G1HeapWastePercent=10
#设置新生代大小,最大60%,默认5%
-XX:G1NewSizePercent=10 -XX:G1MaxNewSizePercent=50

-XX:SurvivorRatio=8 
#在控制台输出GC情况
-verbose:gc 
#gc日志打印到执行日志文件
-Xloggc:./logs/job_execute_gc.log
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime 
#可以生成更详细的Survivor空间占用日志
-XX:+PrintAdaptiveSizePolicy 
#jdk 1.6开始,默认server模式下开启了这个参数,意为当jvm检测到程序在重复抛一个异常,在执行若干次后会将异常吞掉
-XX:-OmitStackTraceInFastThrow 
-XX:-UseLargePages
#指定加载配置文件
--spring.config.location=classpath:/,classpath:/config/,file:./,file:./config/,file:/home/mall-job/conf/

#---当前分布式任务调度采用jvm参数,-Xmn2g,-XX:MaxGCPauseMillis=400调整新生代内存大小,增大暂停时间提高吞吐量---------------------------
-Xms4g -Xmx4g -Xmn2g -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n -XX:+UseG1GC -XX:MaxGCPauseMillis=400 -XX:G1HeapRegionSize=2m -XX:G1MixedGCCountTarget=8 -XX:G1MixedGCCountTarget=8 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -Xloggc:/logs/execute/mall-job-execute-gc.log

提示:更多内容可以访问Clang’s Blog:https://www.clang.asia

猜你喜欢

转载自blog.csdn.net/u012899618/article/details/125326993
今日推荐