前年的文章,备份
前几天一个项目在长时间压测的情况下,发现内存一直飙升,停止压测,内存不释放,明显肯定是内存泄露。把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
相关推荐
Java内存泄露通常涉及对象生命周期和垃圾回收机制。当一个对象不再被任何引用所指向,理论上它应该被垃圾回收器回收。但若长生命周期的对象持有短生命周期对象的引用,即使短生命周期对象已完成其使命,由于引用的...
其次,Garbage Collection(垃圾回收)是一种自动清理不再使用的内存的技术,通常在像Java这样的语言中实现。在C++中,虽然有人试图引入GC,但由于C++的底层特性和对性能的严格要求,GC的实现并不顺畅。因此,C++...
对于防止Java内存泄漏,以下是一些实践建议: 1. 避免在静态字段中存储大量数据或引用。 2. 使用完对象后,及时将其引用设为null,特别是在集合类中。 3. 注意单例模式的实现,确保单例对象在不再使用时能够被垃圾...
4. **无用单元收集堆(Garbage-collected heap)**:Java对象在堆内存中分配,JVM负责自动管理内存,包括对象的创建和销毁,通过无用单元收集(Garbage Collection)机制来回收不再使用的内存,避免内存泄露。...
浅谈Java技术对互联网时代的重要作用 Java技术是互联网时代不可或缺的一部分,自从1996年初Sun公司发布第一个Java开发工具以来,Java语言就成为了跨平台的、面向对象的编程语言。Java语言的优良特性,如可移植性、...
- 注意内存泄漏问题,避免Activity和WebView的生命周期管理不当导致内存泄露。 总之,Android的WebView组件提供了一种强大的方式,让应用能够集成网页内容,实现与网页的交互。但同时,也需要注意权限管理、性能...
而它之所以标记为非安全的,是告诉你这个里面大量的方法调用都会存在安全隐患,需要小心使用,否则会导致严重的后果,例如在通过unsafe类来分配内存时,可能会导致内存泄露。 解决同步问题 解决同步问题的方法有...
Java垃圾回收机制是Java语言的一大特性,它负责自动管理程序中的内存,避免程序员手动处理内存分配和释放。...这个两次标记的过程确保了对象在被回收前有充分的机会进行自我拯救,避免了不必要的内存泄露。
Android AIDL(Android Interface Definition Language)是Android系统中用于进程间通信(IPC,Inter-Process Communication)的一种机制。...同时,对于服务的管理也需特别小心,避免内存泄漏和服务泄露等问题。
6. **注意资源管理**:在Controller中,如果需要处理数据库连接、文件流等资源,确保使用try-with-resources或手动关闭资源,以防止资源泄露。 总之,Spring的Controller默认是单例模式,这要求我们在设计时考虑到...
JavaScript中的函数参数传递机制一直以来都是一...这种机制在一定程度上类似于Java,避免了内存泄露的问题,同时也提供了灵活性,允许开发者通过引用修改对象的状态。了解这一点对于理解和编写JavaScript代码至关重要。