前言
场景:C++通过JNI将数据传输给Java程序
问题:运行一段时间String对象和Char字符不停变大,直到内存溢出(JVM-OOM)
1 过程
- Jmap初步分析头部对象内存占用
PS:jmap -histo:live <pid>,执行该方法会同步执行一次GC,所以,展示的都是无法GC的对象。
发现:String对象有28万个,可能存在String对象被长期持有的现象,初步怀疑是HashMap等缓存持有
- Jmap导出堆栈分析:导出堆栈时String对象是21万个
jmap -dump:live,format=b,file=/root/edr.bin 17994
- 用eclipse-mat打开堆栈文件:通过Histogram看看对象实例数
发现:String对象确实是21万个
- 看看String对象来自于哪里,并将String列表按RetainedHeap倒叙排列
发现:String对象是来自于本地JNI线程,且这个JNI线程还持有大量的内存
- 查看程序线程内存占用情况
发现:存在10个相似的线程,都占用了很多内存,且线程类型还是守护类型,但是无法通过线程名判断是什么线程对象
- 查看线程持有哪些对象
发现:线程持有14759个String对象,基本可以判断是该类(10个)线程没有将JNI-String内存释放
- 最终确认确实是C++JNI相关代码没有释放内存
2 总结
- 灵活应用对象持有和对象被引用关系,来分析内存
- 线程名尽量按模块命名,不要使用默认命名(Thread-*),这样会减少问题定位的难度
爱家人,爱生活,爱设计,爱编程,拥抱精彩人生!
来源:CSDN
作者:qqchaozai
链接:https://blog.csdn.net/qqchaozai/article/details/104044171