Java堆外内存泄露浅谈

前年的文章,备份

前几天一个项目在长时间压测的情况下,发现内存一直飙升,停止压测,内存不释放,明显肯定是内存泄露。把JVM的 Xmx设小了还是无济于事,检查JVM的垃圾回收情况一切都正常,非常困惑,从来没有遇到过这样的情况。经高人指点,知道是JVM的堆外内存泄露,是指我的java程序或者调用到的第三方包直接向OS申请内存,不通过JVM,所以申请的内存不属于jvm管理,自然无法在GC里释放掉。

问题发现了,接下来是找出程序中申请堆外内存的地方,这方面工具很少,一般使用google-perftools查找,详情可以看这篇 《perftools查看堆外内存并解决hbase内存溢出》 http://koven2049.iteye.com/blog/1142768(加HEAPPROFILE=/home/user/perftools/test ,会出现进程被block的情况 )。

当时有个小插曲,perftools一直无法正常使用。于是想了个极端的方式,JVM里有个参数XX:MaxDirectMemorySize 是设置申请OS内存的最大值,我将这个值设成很小的值,结果发现问题更加严重,程序申请不到需要OS内存,程序直接挂起。这个方法直接被否定。 还是要找出最根本的原因,在高人lc_koven 的帮助下,发现是一段解压的代码,造成了大量申请OS内存。主要是调用了deflater 函数,而close方法又没有写在finally里面,这很危险,可能造成OS内存因为异常而无法回收内存。

于是修改代码继续压测,发现情况有好转,但还是有点泄露,既而发现程序中的线程数很大,造成申请了大量内存,但是在压测结束后,内存会被迅速回收。

最后我把那段数据的压缩处理去掉了,那块数据本身就是很紧凑的byte[]。用Gzip也只能压缩到3/4左右。

总结

一般造成堆外内存泄露的原因是压缩和使用NIO,其根本原因是使用了ByteBuffer。关于这个可以看这篇的详细介绍《Byte Buffers and Non-Heap Memory》http://t.cn/aWi1DF

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值