如果线上遇到了OOM,该如何解决?(一)
OOM 意味着程序存在着漏洞,可能是代码或者 JVM 参数配置引起的。这篇文章和读者聊聊,Java 进程触发了 OOM 后如何排查
常说对生产环境保持敬畏之心,快速解决问题也是一种敬畏的表现
为什么会 OOM
OOM 全称 “Out Of Memory”,表示内存耗尽。当 JVM 因为没有足够的内存来为对象分配空间,并且垃圾回收器也已经没有空间可回收时,就会抛出这个错误
为什么会出现 OOM,一般由这些问题引起
内存泄漏:申请使用完的内存没有释放,导致虚拟机不能再次使用该内存,此时这段内存就泄露了。因为申请者不用了,而又不能被虚拟机分配给别人用
内存溢出:申请的内存超出了 JVM 能提供的内存大小,此时称之为溢出
内存泄漏持续存在,最后一定会溢出,两者是因果关系
常见的 OOM
比较常见的 OOM 类型有以下几种
java.lang.OutOfMemoryError: PermGen space
Java7 永久代(方法区)溢出,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。每当一个类初次加载的时候,元数据都会存放到永久代
一般出现于大量 Class 对象或者 JSP 页面,或者采用 CgLib 动态代理技术导致
我们可以通过 -XX:PermSize 和 -XX:MaxPermSize 修改方法区大小
Java8 将永久代变更为元空间,报错:java.lang.OutOfMemoryError: Metadata space,元空间内存不足默认进行动态扩展
java.lang.StackOverflowError
虚拟机栈溢出,一般是由于程序中存在 死循环或者深度递归调用 造成的。如果栈大小设置过小也会出现溢出,可以通过 -Xss 设置栈的大小
虚拟机抛出栈溢出错误,可以在日志中定位到错误的类、方法
java.lang.OutOfMemoryError: Java heap space
Java 堆内存溢出,溢出的原因一般由于 JVM 堆内存设置不合理或者内存泄漏导致
如果是内存泄漏,可以通过工具查看泄漏对象到 GC Roots 的引用链。掌握了泄漏对象的类型信息以及 GC Roots 引用链信息,就可以精准地定位出泄漏代码的位置
如果不存在内存泄漏,就是内存中的对象确实都还必须存活着,那就应该检查虚拟机的堆参数(-Xmx 与 -Xms),查看是否可以将虚拟机的内存调大些
小结:方法区和虚拟机栈的溢出场景不在本篇过多讨论,下面主要讲解常见的 Java 堆空间的 OOM 排查思路
查看 JVM 内存分布
假设我们 Java 应用 PID 为 15162,输入命令查看 JVM 内存分布 jmap -heap 15162
[xxx@xxx ~]# jmap -heap 15162
Attaching to process ID 15162, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.161-b12
using thread-local object allocation.
Mark Sweep Compact GC
Heap Configuration:
MinHeapFreeRatio = 40 # 最小堆使用比例
MaxHeapFreeRatio = 70 # 最大堆可用比例
MaxHeapSize = 482344960 (460.0MB) # 最大堆空间大小
NewSize = 10485760 (10.0MB) # 新生代分配大小
MaxNewSize = 160759808 (153.3125MB) # 最大新生代可分配大小
OldSize = 20971520 (20.0MB) # 老年代大小
NewRatio = 2 # 新生代比例
SurvivorRatio = 8 # 新生代与 Survivor 比例
MetaspaceSize = 21807104 (20.796875MB) # 元空间大小
CompressedClassSpaceSize = 1073741824 (1024.0MB) # Compressed Class Space 空间大小限制
MaxMetaspaceSize = 17592186044415 MB # 最大元空间大小
G1HeapRegionSize = 0 (0.0MB) # G1 单个 Region 大小
Heap Usage: # 堆使用情况
New Generation (Eden + 1 Survivor Space): # 新生代
capacity = 9502720 (9.0625MB) # 新生代总容量
used = 4995320 (4.763908386230469MB) # 新生代已使用
free = 4507400 (4.298591613769531MB) # 新生代剩余容量
52.56726495150862% used # 新生代使用占比
Eden Space:
capacity = 8454144 (8.0625MB) # Eden 区总容量
used = 4029752 (3.8430709838867188MB) # Eden 区已使用
free = 4424392 (4.219429016113281MB) # Eden 区剩余容量
47.665996699370154% used # Eden 区使用占比
From Space: # 其中一个 Survivor 区的内存分布
capacity = 1048576 (1.0MB)
used = 965568 (0.92083740234375MB)
free = 83008 (0.07916259765625MB)
92.083740234375% used
To Space: # 另一个 Survivor 区的内存分布
capacity = 1048576 (1.0MB)
used = 0 (0.0MB)
free = 1048576 (1.0MB)
0.0% used
tenured generation: # 老年代
capacity = 20971520 (20.0MB)
used = 10611384 (10.119804382324219MB)
free = 10360136 (9.880195617675781MB)
50.599021911621094% used
10730 interned Strings occupying 906232 bytes.
通过查看 JVM 内存分配以及运行时使用情况,可以判断内存分配是否合理
另外,可以在 JVM 运行时查看最耗费资源的对象,jmap -histo:live 15162 | more
JVM 内存对象列表按照对象所占内存大小排序
明显看到 CustomObjTest 对象实例以及占用内存过多
可惜的是,方案存在局限性,因为它只能排查对象占用内存过高问题
其中 "[" 代表数组,例如 "[C" 代表 Char 数组,"[B" 代表 Byte 数组。如果数组内存占用过多,我们不知道哪些对象持有它,所以就需要 Dump 内存进行离线分析
jmap -histo:live 执行此命令,JVM 会先触发 GC,再统计信息
文章转自公众号:龙台的技术笔记
-
在java总 如何解决 传参乱码问题killads • 7198浏览 • 0回复
-
Flutter - 解决 混合开发iOS脚本打包 遇到 的问题level • 1.4w浏览 • 0回复
-
如何解决 android studio常见安装完成后出现的问题epeppanda • 9820浏览 • 0回复
-
鸿蒙设备开发环境搭建过程中 遇到 的问题与 解决 方法mb5f857b091f3d6 • 1.3w浏览 • 0回复
-
6月2日已曝光信息汇总,再加上 一 车爆料,测试你悟性的时候 到了开源基础软件社区官方 • 2.0w浏览 • 19回复
-
HarmonyOS应用框架 如何解决 多设备交互问题?开源基础软件社区官方 • 1.0w浏览 • 0回复
-
等了20天,礼物终于收 到了界祏 • 5587浏览 • 8回复
-
HDC2021技术分论坛:异构组网 如何解决 共享资源冲突?HarmonyOS开发者 • 4694浏览 • 0回复
-
异构组网 如何解决 共享资源冲突?开源基础软件社区官方 • 6534浏览 • 1回复
-
如何解决 HarmonyOS sdk的bug--AlphabetIndexer组件的bug 解决 思路软通夏德旺 • 9828浏览 • 1回复
-
如果 让你重来,你会选择哪种编程语言,为什么?开源活动小助手 • 1.4w浏览 • 39回复
-
社区贡献- 如何解决 合入冲突zhushangyuan_ • 2849浏览 • 1回复
-
Redis 如何解决 频繁的命令往返造成的性能瓶颈kevinaoc • 5425浏览 • 0回复
-
硬核 | Kafka 如何解决 消息不丢失?ltolll • 2926浏览 • 0回复
-
TiKV缩容不掉 如何解决 ?lemonvita • 3454浏览 • 0回复
-
EventMesh 如何解决 SaaS组合式应用集成标准化问题罗锦荣AlexLuo • 8484浏览 • 14回复
-
Spring Boot 如何解决 多个定时任务阻塞问题?love374 • 4011浏览 • 0回复
-
如果 线上 遇到了 OOM , 该 如何解决 ?(二)Handpc • 2458浏览 • 0回复
-
如何解决 JumpServer 连接 Linux 资产,资产乱码?coxi_vv • 922浏览 • 0回复