ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

线上发生OOM

2022-02-25 10:34:07  阅读:190  来源: 互联网

标签:java dump OOM 发生 XX GC 线上 heap 内存


线上jvm故障处理思路

报错分类
java.lang.OutOfMemoryError: Java heap space ------>java堆内存溢出

此种情况最常见,一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露,需要通过内存监控软件查找程序中的泄露代码,而堆大小可以通过虚拟机参数-Xms,-Xmx等修改。

java.lang.OutOfMemoryError: PermGen space 或 java.lang.OutOfMemoryError:MetaSpace ------>java方法区

(java8 元空间)溢出了,一般出现于大量Class或者jsp页面,或者采用cglib等反射机制的情况,因为上述情况会产生大量的Class信息存储于方法区。此种情况可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改。另外,过多的常量尤其是字符串也会导致方法区溢出。

java.lang.StackOverflowError ------> 不会抛OOM error,但也是比较常见的Java内存溢出。

JAVA虚拟机栈溢出,一般是由于程序中存在死循环或者深度递归调用造成的,栈大小设置太小也会出现此种溢出。可以通过虚拟机参数-Xss来设置栈的大小。

首先说明:在此不是解决上线bug或者容器崩溃的错误,而是解决OutOfMemoryError与StackOverflowError,出现了这个错误,虚拟机不能用,但是要里面恢复,针对这样的问题,我们来聊聊一些处理的办法,结合我们前面学习的虚拟机的配置与工具的使用,进行实战整理。

  1. 线上出现访问很慢、超时、或者有的直接报错运行时的错误,我们看到错误信息,根据状态去定位。检查是否是网络问题 (cdn,dns,nginx),运维应该快速的排查。

  2. 检查jvm时候正常工作,检查日志是否有遭难性的错误,如果jvm进程正常,应用中出现了灾难性的,那就应用程序的性能问题或者bug,赶紧加班去吧。

  3. 前面这个过程很快要完成,估计在问题出现的30’就的搞定,搞不定估计老老大要出面了,如果问题确定是开发的问题,日志给开发,重启应用服务,开发解决问题,发布bug版本。

保存状态信息
jmap -dump:format=b,file=/tmp/logs/dump.phrof 14632 #生成转储存快照 dump 文件(最为常用)

jmap -heap 14632 > /tmp/logs/heap.log

jstat -gcutil 14632 > /tmp/logs/stat.log

jstack -l 14632 > /tmp/logs/stack.log
jmap(堆内存分析)

一定要注意,触发Full GC和不触发Full GC的情况,因为我们必须要通过控制变量法,对照地来实验结果。当堆异常时,想要获得快照,如此时使用GC后快照,则必然会破坏当前的堆样本。因此,我们针对堆 heap 的分析,必定是需要2份以上快照,1份是有问题的 heap dump,通常是异常下未GC的情况;另一份是项目启动后输出,或GC后输出的比较正常的 heap dump。

生成转储存快照 dump 文件(最为常用)! 

jmap -dump:format=b,file=/dump.phrof pid
jstack(栈分析)
jstack -l pid >/var/thread.txt

获取 Thread dump,并输出到 /var/thread.txt 文件
jps(显进程信息)
jps -v

显示Java进程ID 和 类的名称, 以及传递给JVM的启动参数等
jstat(查看GC相关信息)
jstat -gcutil pid

详细显示GC相关的堆信息,查看GC的次数,及时间(非常实用)
jinfo( 动态 JVM 参数控制)
jinfo flags pid

所有的vm参数设置的值,可看垃圾回收器的种类
jhat(分析 heapdump 文件)
jhat -J-Xmx2048M heap.phrof

可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言(当然,能拿到 dump 文件,还是推荐拿到本地使用工具来查看,而不是在服务器上直接查看)。

-J 后可以跟 JVM 的参数;
jvm堆常用参数
参数描述
-Xms 堆内存初始大小,单位m、g(堆内存下限)
-Xmx(MaxHeapSize) 堆内存最大允许大小,一般不要大于物理内存的80%(堆内存上限)
-XX:PermSize 非堆内存初始大小,一般应用设置初始化200m,最大1024m就够了 (元数据区初始)
-XX:MaxPermSize 非堆内存最大允许大小(元数据最大值)
-XX:NewSize(-Xns) 年轻代内存初始大小(一般小于Xms)
-XX:MaxNewSize(-Xmn) 年轻代内存最大允许大小,也可以缩写(一般小于Xmx)
-XX:SurvivorRatio=8 年轻代中Eden区与Survivor区的容量比例值,默认为8,即8:1
-Xss 堆栈内存大小
-XX:NewRatio 新生代与老年代的比率 默认是2,老年代是新生代的2倍
根据日志信息排查问题

根据stat与heap区情况,可以大概的定位到是哪个区域发生了,通常老说是老年代,为什么,因为新生代在空间不足的情况下会触发GC,如果一直不足,一直GC,那么分配的对象很快就进入老年代,而又得不到释放。那么我们就需要检查哪些对象比较大。根据jstack信息,找到运行的线程以及可能报错的线程位置,Dump文件查看哪些对象较多较大

Jprofiler持续跟踪重启后的内存使用,对象分配,线程运行情况,基本上来说可以定位到错误的地方。

这样如果还找不到问题,那可能太隐蔽了,需要把相关的人召集起来,针对问题,集中解决,知道问题最终解决。

 

如有侵权联系邮箱:1757710613@qq.com

标签:java,dump,OOM,发生,XX,GC,线上,heap,内存
来源: https://www.cnblogs.com/l0vE/p/15934772.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有