请教一个 Java 内存占用的问题

2020-03-04 14:26:49 +08:00
 CodeXx
跑着的 Java 程序突然开始频繁报 java.lang.OutOfMemoryError: Java heap space 错误,应该是内存不足。想查一下是哪里有内存泄漏,用 jmap -heap 查到堆占用也就 1g 左右。但是任务管理器中这个程序占了 2g 多内存。用 jconsole 查看非堆内存也就占了 100MB,想问下还有 1g 多内存是从哪里产生的,这种问题还有什么好的方法可以排查吗

Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 2128609280 (2030.0
NewSize = 44564480 (42.5MB)
MaxNewSize = 709361664 (676.5MB
OldSize = 89653248 (85.5MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.79687
CompressedClassSpaceSize = 1073741824 (1024.0
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
capacity = 380633088 (363.0MB)
used = 142412024 (135.81468963623047MB)
free = 238221064 (227.18531036376953MB)
37.41451505130316% used
From Space:
capacity = 153092096 (146.0MB)
used = 98938800 (94.35539245605469MB)
free = 54153296 (51.64460754394531MB)
64.62698113428404% used
To Space:
capacity = 160956416 (153.5MB)
used = 0 (0.0MB)
free = 160956416 (153.5MB)
0.0% used
PS Old Generation
capacity = 1143472128 (1090.5MB)
used = 856911104 (817.214111328125MB)
free = 286561024 (273.285888671875MB)
74.9393958118409% used

31023 interned Strings occupying 3682496 bytes.
5257 次点击
所在节点    Java
12 条回复
nickchenyx
2020-03-04 15:21:38 +08:00
看你这个打印有点问题啊,你的 From&To Space 占用太高了,young gen 里,From&To 和 eden 的比例应该是 2:8,你这个不要修改默认配置。

这里看你的 heap usage 没啥问题啊,在 jvm 启动的时候加上参数打印一下在 gc 的时候以及 oom 的时候内存分布情况

-XX:ErrorFile=./hs_err_pid%p.log -XX:HeapDumpPath=./ -Xloggc:./gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintHeapAtGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps
jiashun
2020-03-04 15:27:00 +08:00
看程序 GC 正常不,如果 GC 正常,没有频繁 GC (堆内存对象正常回收),可以把目光转向非堆内存,排查下哪里用到了 NIO,有没内存泄露
yidinghe
2020-03-04 15:33:41 +08:00
如果光看总量看不出问题,那么就要把内存 dump 出来看具体哪些对象占用了内存
yanyueio
2020-03-04 15:42:13 +08:00
与上面几位大佬说的基本思路一致,主要看 GC 是否正常(一般就是这里),不行的话在看具体的对象占用内存量。

个人觉得栈的话一般不用看,至少我还没有遇到过栈空间问题。

补一补 JVM 的知识吧,类似于搞 C/C++ 的必须知道进程的结构一样。
CodeXx
2020-03-04 16:59:49 +08:00
@nickchenyx
@jiashun
@yidinghe
@yanyueio
感谢各位提供思路
CodeXx
2020-03-04 17:59:54 +08:00
@yidinghe dump 出来的文件 1g 多,内存占用高的是 org.apache.mina.transport.socket.nio.NioSocketSession 占了 400 多 m。但程序系统占用了 2g 多,感觉还有一部分内存没有查看到
liuming
2020-03-04 18:36:33 +08:00
看 heap usage,实际堆空间显示还有不少空闲,当需要在堆上分配空间的时候不该出现 OOM: Java heap space 这样的错误提示,除非系统的空闲内存不足了,也就是堆外内存有泄漏、终于耗尽了系统的剩余内存,可是如果是这种情况,系统的表现不该是死机之类的么?
CodeXx
2020-03-04 19:27:02 +08:00
@liuming 抱歉忘了说,这个是没报错的时候打印的
gaius
2020-03-04 19:27:18 +08:00
日志里打印的是什么样的,mina netty 这种多和堆外泄露有关,netty 的话会抛自己的异常,mina 不清楚,而且也不该是 heap space。
CodeXx
2020-03-04 22:22:05 +08:00
@gaius 确实可能是堆外的,我手动 gc 后堆内存只占几十 m 了,但是程序占内存还是 2g。日志报的错贴出来了,请问大佬这种堆外泄漏要怎么查啊。
liuming
2020-03-05 00:15:30 +08:00
看了下 Thumbnailator 在 github 上的 issue,不少堆上出 OOM 的……比如 https://github.com/coobird/thumbnailator/issues/111,根据这 issue 里作者的说法,Thumbnailator 挺耗内存的,尤其是你这貌似在多线程使用……不过这应该不是程序内存占用远远大于堆实际占用的原因,但应是导致 OOM 的原因。怎么排查堆外泄漏可以参考下这个视频,视频里介绍了不少实际工具: <amp-youtube data-videoid="JoQN4xoXY5Y" layout="responsive" width="480" height="270"></amp-youtube>
CodeXx
2020-03-05 17:45:43 +08:00
@liuming 好的,感谢

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

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

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

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

© 2021 V2EX