JVM问题排查

参数配置

先确保jvm有以下配置,可以在遇到异常时方便快速排查。

#Java fatal error(致命错误即jvm crash)日志目录
-XX:ErrorFile=/logs/hs_err_pid%p_%t.log  

# gc日志文件名
-Xloggc:gc.log 

# oom dump
-XX:+HeapDumpOnOutOfMemoryError 用于内存溢出产生hprof文件
-XX:HeapDumpPath=/heapdump

# gc日志
-Xloggc:gc.log 日志文件名
-XX:+PrintGCDetails  打印GC详细信息
-XX:+PrintGCDateStamps 打印GC停顿时间

JVM崩溃进程消失

1.查看是否生产hs_error文件。(jvm crash)

2.查看是否生成dump文件。(oom)

3.查看demesg消息。(系统kill)

 当机器内存被占满,系统自动选择一个占用内存最大的进行kill掉。

# dmesg:用来显示内核相关的信息。
dmesg|grep -i kill | less 或 dmesg|grep kill

OOM

  Exception in thread “main” java.lang.OutOfMemoryError: unable to create new native thread

  没有足够的内存空间给线程分配java栈.

  1. 可指定-Xss来减少单个thread stack的大小。
  2. 通过jstack排查线程数量,确认是否存在大量创建线程的情况。
    #查看进程线程数    
    top -Hp $pid  
    ps -T -p $pid 
    
    # 通过jstack 分析线程
    jstack $pid

Exception in thread “main” java.lang.OutOfMemoryError: Java heap space

  堆的内存占用已经达到-Xmx设置的最大值 

  1. 设置更大-Xmx值。
  2. 通过MAT或其他工具分析dump文件确认是否存在异常。

  Caused by: java.lang.OutOfMemoryError: Metaspace

元数据区的内存占用已经达到-XX:MaxMetaspaceSize设置的最大值,

  1. 通过-XX:MaxMetaspaceSize来进行调整。
  2. 通过jmap dump内存日志分析元数据是否存在重复创建类加载器加载类的情况。
    #打印类加载器信息
    jmap -F -clstats PID 
    # dump
    jmap -dump:format=b,file=./a.hprof PID

java.lang.OutOfMemoryError: GC overhead limit exceeded

GC开销限制,JVM花费了98%的时间进行垃圾回收,而只得到2%可用的内存,导致频繁的进行内存回收(连续5次以上垃圾回收)

  1. 通过gc日志和dump内存分析是否存在异常。
  2. 优化heap区域分配比例

FullGC频繁

1. 通过gc日志判断引起fullgc的区域。

MetaSpace 引起的fullgc:可通过jmap -histo $pid  和 jmap -clstats $pid 分析元数据空间是否重复加载相同类导致空间不足。

        Metadata GC Threshold:metaspace空间不能满足分配时触发,这个阶段不会清理软引用;
        Last ditch collection:经过Metadata GC Threshold触发的full gc后还是不能满足条件,这个时候会触发再一次的gc cause为Last ditch collection的full gc,这次full gc会清理掉软引用。

老年代 引起fullgc

  1. 新生代对象转入及创建为大对象时出现老年代空间不足现象,当执行Full GC后空间仍然不足抛出java.lang.OutOfMemoryError: Java heap space。以上两种状况引起的Full GC,调优时应尽量做到让对象在Minor GC阶段被回收、让对象在新生代多存活一段时间及不要创建过大的对象及数组。

  2. CMS GC时出现promotion failed和concurrent mode failure:promotion failed是在进行Minor GC时,survivor space放不下、对象只能放入老年代,而此时老年代也放不下造成的。concurrent mode failure是在执行CMS GC的过程中同时有对象要放入老年代,而此时老年代空间不足造成的(有时候“空间不足”是CMS GC时当前的浮动垃圾过多导致暂时性的空间不足触发Full GC)。对措施为:增大survivor space、老年代空间或调低触发并发GC的比率。

  3. 堆中分配很大的对象。大量连续内存空间的java对象,例如很长的数组,会直接进入老年代,而老年代虽然有很大的剩余空间,但是无法找到足够大的连续空间来分配给当前对象,此种情况就会触发JVM进行Full GC。CMS垃圾收集器提供了一个可配置的参数,即-XX:+UseCMSCompactAtFullCollection开关参数,用于在“享受”完Full GC服务之后额外免费赠送一个碎片整理的过程,内存整理的过程无法并发的,空间碎片问题没有了,但提顿时间不得不变长了,JVM设计者们还提供了另外一个参数 -XX:CMSFullGCsBeforeCompaction,这个参数用于设置在执行多少次不压缩的Full GC后,跟着来一次带压缩的。

CUP高

  top -c找到CPU高的进程PID
  top -Hp PID shift+t查看cpu使用率高的线程 
  printf '%x\n' 线程pid将线程pid转换为16进制的nid
  jstack PID | grep -A 20 nid  # 获取线程堆栈信息
  jstack PID | grep nid -C5 –color 获取线程堆栈信息
    - 关注 WAITING、TIMED_WAITING、BLOCKED状态线程
    - jstat -gcutil pid 3s 10分析是否存在频繁GC
    - pidstat -w pid分析上下文切换

内存高

内存组成

​​​​​​​

问题排查

free -h 命令查看机器内存情况。
通过jmap -heap $pid  or jstat -gccapacity $pid 查看进程占用内存情况,确定占用内存高的区域。
堆外内存:pmap -x $pid | sort -rn -k3 | head -30 查看对应pid倒序前30大的内存段。

线程池满

  1. 通过jstack $pid 导出堆栈信息。
  2. 排查堆栈信息中是否存在大量线程等待。
  3. 业务层面排查线程处理是否能快速完成。

  • 35
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

larry_seven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值