Java堆外内存溢出问题排查,top命令下java服务res值上升

本文记录了一次在Linux环境下排查Java服务内存泄漏的过程。通过使用jmap、jstack等工具结合GC日志,最终定位问题为native heap内存使用不当导致服务宕机,并给出了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前几天写了一套java服务用于对接视频单位的sdk接口,但是项目环境测试的时候出现了问题:

         在linux环境下使用top命令查看java命令的mem比值一直在缓慢的增加,第二天出现了服务宕机的情况,生成hs_err的log                   

          测试环境的配置:阿里云ecs,总物理内存7.6g 。 java服务启动参数xmx为total的7/10

          服务器上就我这一个吃大内存的服务,只有我自己用于测试使用,按照常理来说应该够用才对。

 

问题排查过程:

首先确定是否是内存溢出的问题 ? 

 过程:使用java自带的一些命令,jmap ,jstack等命令以及jconsole远程监控结合gc的日志进行gc情况的排查,java堆因为内存较小              的问题  除了eden的gc频率比较快一点,其他都在正常课接受范围之内。   dump下来的内存快照用mat分析也没发现问题。

结论:不是堆内存问题!

top命令下查看到的mem总数 = 系统自身耗内存 + java heap + no heap(meta space+code cache 等)*线程数 + 虚拟机进程本身 + 虚拟机栈(线程栈)*线程数 + native heap

那么既然java heap没有发现问题,再结合服务中使用jna调用so,其中so中涉及到大量的socket与缓冲区还有视频数据的接收处理等

那么怀疑native heap的使用除了问题?

过程:首先确定下XX:MaxDirectMemorySize的默认值是多少(我没有显示的去设置maxSize,关注1.8的时候对直接内存的印象还停留在旧版本的默认64m!!!)

经过一番查阅发现 1.8版本最大可以直接内存可以使用参数-XX:MaxDirectMemorySize设置,如不设置,默认值为java heap 的max最大值,-Xmx - from区域的大小(几乎等同xmx)。native heap 达到最大值,不会触发gc,如果释放不了足够的空间,引发宕机的风险。

见源码分析L:http://hllvm.group.iteye.com/group/topic/27945

然后在结合刚才的内存分配情况,会出现的内存竞争,不宕机才怪,果然!修改完参数3/10之后,项目稳定了很多!至此问题算是圆满解决!

 

 

如果该方案还没有解决你的问题,那我推荐你使用google-perftools一款google的良心工具,在linux上下载安装完成后在项目启动前加上一些启动参数的配置,就可以经过项目一段时间运行,可以统计出来内存异常的代码块了!

有关于下载的链接还有使用方式以及结构化输出后的参数说明:

下载地址:https://github.com/gperftools/gperftools

如果操作系统64位还需要先安装 libunwind库:http://download.savannah.gnu.org/releases

使用方式和参数详解:https://blog.csdn.net/turkeyzhou/article/details/8794188

如有问题探讨,可留言,看到及时回复!

### Java 内存溢出排查常用命令排查 Java 内存溢出问题时,常用的命令工具可以帮助快速定位内存使用情况、生成堆转储文件、分析线程状态等关键信息。以下是一些常见的命令及其用途: #### 1. 查看 JVM 参数配置 使用 `jinfo` 命令可以查看 Java 进程的 JVM 参数配置,包括堆内存大小、垃圾回收器类型等信息: ```bash jinfo -flags <pid> ``` 其中 `<pid>` 是 Java 进程的 ID。通过该命令可以确认 JVM 的内存配置是否合理,如 `-Xmx` 和 `-Xms` 参数设置的最大堆内存是否过小或过大 [^3]。 #### 2. 查看 Java 进程内存使用情况 使用 `jmap` 命令可以查看 Java 进程的堆内存使用情况,包括 Eden 区、Survivor 区、老年代等的使用情况: ```bash jmap -heap <pid> ``` 该命令输出的信息有助于判断内存分配是否合理,以及是否出现了内存溢出的迹象 。 #### 3. 生成堆转储文件 当发生内存溢出时,可以通过以下 JVM 参数配置在内存溢出时自动生成堆转储文件: ```bash -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<path> ``` 其中 `<path>` 是堆转储文件的保存路径。生成的 `.hprof` 文件可以通过内存分析工具(如 MAT、VisualVM)进行深入分析,找出内存泄漏的根源 [^1]。 #### 4. 查看系统整体资源使用情况 使用 `top` 命令可以查看系统的整体资源使用情况,包括 CPU 和内存的使用率,帮助判断 Java 进程是否占用过多内存: ```bash top ``` 在 `top` 输出中,可以通过查看 `RES` 列(物理内存使用量)来判断 Java 进程的内存使用情况 [^3]。 #### 5. 分析线程堆栈信息 使用 `jstack` 命令可以打印出 Java 进程的线程堆栈信息,帮助分析线程阻塞、死锁等问题: ```bash jstack [-l] <pid> ``` 在内存溢出排查中,线程堆栈信息有助于判断是否存在线程泄漏或线程阻塞导致的内存问题 [^5]。 #### 6. 查看 Java 进程的类加载情况 使用 `jstat` 命令可以查看 Java 进程的类加载情况,包括已加载的类数量、卸载的类数量等: ```bash jstat -class <pid> ``` 该命令有助于判断类加载是否过多,导致方法区(元空间)内存溢出 。 #### 7. 监控垃圾回收情况 使用 `jstat` 命令可以监控 Java 进程的垃圾回收情况,帮助判断是否存在频繁的 Full GC 或 GC 效率低下: ```bash jstat -gc <pid> ``` 该命令输出的信息包括 Eden 区、Survivor 区、老年代的使用情况,以及 GC 的执行次数和耗时 。 #### 8. 使用 `jcmd` 生成堆直方图 `jcmd` 是一个多功能的 JVM 管理工具,可以用于生成堆直方图,帮助分析内存中对象的分布: ```bash jcmd <pid> GC.class_histogram ``` 该命令输出的信息包括每个类的实例数量和占用内存大小,有助于发现内存泄漏的对象 。 #### 9. 使用 `jmap` 生成堆直方图 `jmap` 也可以用于生成堆直方图,帮助分析堆内存中对象的分布情况: ```bash jmap -histo <pid> ``` 该命令输出的信息包括每个类的实例数量和占用内存大小,有助于发现内存泄漏的对象 [^3]。 #### 10. 使用 `jvisualvm` 进行图形化分析 `jvisualvm` 是一个图形化工具,集成了多种性能分析功能,包括内存分析、线程分析、堆转储分析等。可以通过以下命令启动: ```bash jvisualvm ``` 启动后,可以连接到目标 Java 进程,实时监控内存使用情况,并加载堆转储文件进行深入分析 [^1]。 --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值