请教 Java OOM 及 JVM 相关的问题

2024-10-17 17:22:42 +08:00
 superhot

背景

  1. AWS EC2 t3.medium 实例,Amazon Linux 2 系统,4GB 内存。
  2. Java 启动时 Heap 的配置为 -Xmx2847m,大概是给其他服务留 1G 左右内存,其余全部分配给 JVM 。
  3. 结合日志和后台监控发现频繁出现 OOM 导致 Tomcat 重启的问题。

问题

  1. 现在每个实例的平均内存使用率在 93% 左右,此现象是否正常?
  2. 保持当前 EC2 实例配置不变的情况下,给 JVM Heap 分配多大内存比较合适?有什么可以拿来当作判断的依据吗?
  3. 除了 Heap 之外,JVM 还有 Metaspace 、CodeCache 、DirectByteBuffers 等等,这些 Heap 之外的部分可能吃掉多少内存?有什么可以拿来当作判断的依据吗?
  4. 如何分析 OOM 可能的情况?/usr/share/tomcat 目录下有个 hs_err_pid 前缀的日志文件,似乎在 OOM 时会输出相关错误信息,但根本看不懂……

一年后端经验的 CRUD Boy 没系统学过 Java ,不了解 JVM ,突然让去解决 OOM 的问题,实在懵逼,不知从何下手,请各位 Java 大佬们给点建议,救救本菜,谢谢大家!

5477 次点击
所在节点    程序员
43 条回复
BBCCBB
2024-10-17 17:30:10 +08:00
堆内内存的话, dump 一份内存下来看占用内存的都是什么东西.
2Nfree
2024-10-17 17:30:38 +08:00
可以用 JVM 参数 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/heapdump 导出 OOM 时的 heap dump ,然后用工具分析,或者直接在应用程序运行的时候使用 jmap 导出当前对象分布的情况进行分析,推荐用这个: https://arthas.aliyun.com/doc/
INCerry
2024-10-17 17:33:17 +08:00
什么版本的 Java ?如果版本高只想解决问题,那先:

-XX:+UnlockExperimentalVMOptions
-XX:+UseShenandoahGC
-XX:ShenandoahGCHeuristics=compact
Geekerstar
2024-10-17 17:34:29 +08:00
把这个 hs_err_pid 日志发出来,我最近也遇到 OOM 了,能帮忙排查下。可以看我最近发的一个帖子。
defunct9
2024-10-17 17:38:09 +08:00
升级 ec2 ,给 8G 内存
wenning
2024-10-17 17:49:13 +08:00
springboot 的话加上 actuator, 配合 prometheus, grafana 看看 jvm 相关的使用情况; 90%的占用肯定不正常了, 相当于比较吃紧了, 如果来点压力就挂了, 再留一点内存给系统, 否则内存满了直接会被系统 kill
ZZ74
2024-10-17 17:54:27 +08:00
现在每个实例的平均内存使用率在 93% 左右,此现象是否正常? 正常。
参考这个帖子 https://www.v2ex.com/t/1078482?p=1#reply22 贴出 hs_err_pid 内容。贴给 AI 都会给你分析。
xiwolaisi
2024-10-17 18:08:39 +08:00
jvm dump 分析网站,我自己懒得跑 MAT 的时候就用这个👻
https://heaphero.io/heap-index.jsp#header
jorneyr
2024-10-17 18:23:00 +08:00
例如代码里把 1G 文件全部一次性读入内存,先分析代码的原因。
paranoiagu
2024-10-17 18:28:34 +08:00
给太高了吧。
paranoiagu
2024-10-17 18:29:05 +08:00
除了堆内存还有堆外内存。
superhot
2024-10-17 18:29:47 +08:00
@INCerry Java11 ,应该不算很高

@Geekerstar 链接贴在附言里了,函数名修改过,先谢过老哥,我去帖子学习下

@defunct9 只有升配置加内存这一条路了吗。。7 80 个实例,有点顶不住 ; w ;

@ZZ74 问过 copilot ,没什么干货

@wenning 我也有点怀疑这个


@xiwolaisi
@BBCCBB
@2Nfree
感谢提供思路,只是听过名词,对这些还没什么清晰的认识,我再研究研究
sagaxu
2024-10-17 18:45:59 +08:00
-Xmx 调小一点试试,比如 2000m

总内存只有 4G ,设置-Xmx2847m 一定会 OOM
yuemingming
2024-10-17 19:57:24 +08:00
「结合日志和后台监控发现频繁出现 OOM 导致 Tomcat 重启的问题。」
贴一下后台异常重启的日志呢。
正常来说一个系统平稳运行是不应该 OOM 的。即使你的堆内存比较小,但是只要系统使用了内存之后正常释放,也是可以通过垃圾回收释放这些内存的。就是可能垃圾回收的频率比较高。
如果频繁 OOM 的话,两种情况,一种是正常情况,处理请求的过程中,需要大量的内存,但是所有可回收的都已经回收了,还是不够。另一种就是代码写的有问题,该回收的没回收。
堆内存配置看着比较合理,正常来说留一个 G ,一部分操作系统需要,一部分 JVM 的一些其他机制也需要堆外内存。比如线程堆栈。
yuemingming
2024-10-17 19:58:49 +08:00
@sagaxu 看着楼主的意思就是 JVM 内部的 OOM 吧。老哥说的这种情况是堆外内存留少了,然后系统把 JVM 进程给干了。
superhot
2024-10-17 20:24:48 +08:00
@yuemingming 在 Tomcat 的 Catalina 日志里看到的内容,正在连续处理请求的时候,每条日志的时间间隔小于 1s ,但明显该次请求还没处理完毕,上一条还是普通异常处理部分的日志,接下来就变成了类似 Tomcat startup 之类的信息,跟上一条隔了大概 30s ~ 70s 左右,以此来判断是重启过了。不过你说的这点确实需要再确认一下,这个重启到底跟 OOM 有没有关系。
sagaxu
2024-10-17 21:02:50 +08:00
@yuemingming

/proc/meminfo:
MemTotal: 3964656 kB
MemFree: 114400 kB
MemAvailable: 3092 kB

他这很明显就是被 OOM killer 杀掉了。

Java 8 之后若没设置 MaxDirectMemorySize ,默认跟 Xmx 是 1:1 的,OP 的机器 Xmx 超过 2g 有较大几率 OOM 。
superhot
2024-10-17 21:15:41 +08:00
@sagaxu 请问这种情况下,怎样分配内存比较合理呢?我目前的想法也是先减少 Heap 大小试试看,但不知道靠什么来判断 `-Xmx` 的值设为多少比较合适。跟组长提方案的时候得拿证据……头疼。
zhouhu
2024-10-17 21:32:16 +08:00
@superhot 你们业务量很大?最好 xmx 和 xms 设置为一样的 。一般的业务 1G 就好了。

Xmx2847m 为什么是 2847 啊,虽然 G1 会自动对齐。
sagaxu
2024-10-17 21:33:40 +08:00
@superhot 需要结合 GC 日志来分析,降低 Xmx 会提高 GC 频率,降低系统吞吐并增加系统延迟。调低 Xmx 后如果性能不达标,一般尝试调整参数优化 GC ,升级 JVM 版本可能也有些帮助。Tomcat 本身也有一些参数可以调整。如果这些都解决不了问题,那只能扩容或者优化代码了。

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

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

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

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

© 2021 V2EX