Eclipse Memory Analyzer以及内存泄露的原因
2014-05-09 11:04
302 查看
Eclipse Memory Analyzer是一个非常棒的堆内存分析工具,是JDK自带的堆分析工具jhat的一个非常好的替代品,能够快速地定位Java内存泄露的原因。
可能有的同学会问,JVM不是号称自动内存管理,GC会自动垃圾回收,Java怎么会有内存泄露,不会搞错吧?当然不会^_^, Java的内存泄露不同于C/C++的内存泄露,C/C++的内存泄露是由于使用了堆内存(new/malloc)却没有释放(delete/free),导致无法再使用到该内存片,而Java的内存泄露是无谓地引用了一些垃圾的对象,譬如我们有一个Map对象,不断往里面放对象,实际的场景可能是这些对象不会再被使用到,这时候,这部分数据本身是垃圾的(因为不会再被使用),但实际上JVM会不会释放它(因为还被Map)引用着,这就是Java的内存泄露。
在开始分析之前,我们先想想,在编程这个角度上,我们如何避免堆内存泄露呢?实际上java.lang.ref这个包已经为我们提供了一种问题解决方案。Java的引用有4种:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、幻影引用(Phantom Reference),关于这部分介绍的文章一大批,此处就不做深入,我们只需要知道如下的信息:
强引用:除非将引用置为null,否则JVM不会对它垃圾,这是最常用的引用方式
软引用:在堆内存不足的时候,GC会将其垃圾回收
弱引用:每次GC都会将其垃圾回收
幻影引用:跟没有引用一样,每次获得的都是空的,没有太多使用的意义,仅是为了追踪对象在JVM的状态
一般对于大数据量的Cache信息或大对象,使用软引用/弱引用是一种非常好的习惯,或者至少使用一种淘汰算法,避免在堆内存拥挤大量的对象导致内存不足,如下是两个非常好的JDK默认提供的HashMap替代者:
org.apache.commons.collections.map.ReferenceMap:支持强引用/软引用和弱引用来存储key/value对
org.apache.commons.collections.map.LRUMap:可以控制总容量,采用LRU淘汰算法,将不常使用的数据淘汰出去
介绍完一些背景,我们开始进入主题。在开始分析之前,我们需要先dump下JVM的堆内存信息(虽然Eclipse Memory Analyzer直接attach到JVM上获取栈再分析,实际应用价值不大)
jmap –dump:file=test.bin {pid}
现在我们有了test.bin这个堆文件,使用Eclipse Memory Analyzer打开,分析完堆,我们可以选择“Leak Suspects Report”进行内存泄露分析。通过这个视图,我们可以大概得到内存泄露的初步结论
Historygram也是一个非常常用的视图,可以获得堆中对象的数据统计,有排序、过滤的功能,非常好用
Eclipse Memory Analyzer还包括如下功能:
在Historygram视图中右击对象弹出的功能框中,可以获得对象相互引用的关系的功能
Dominator Tree的视图采用Tree的方式来展现整个栈对象相互引用的情况
OQL视图支持使用OQL语言来查询对象信息
可能有的同学会问,JVM不是号称自动内存管理,GC会自动垃圾回收,Java怎么会有内存泄露,不会搞错吧?当然不会^_^, Java的内存泄露不同于C/C++的内存泄露,C/C++的内存泄露是由于使用了堆内存(new/malloc)却没有释放(delete/free),导致无法再使用到该内存片,而Java的内存泄露是无谓地引用了一些垃圾的对象,譬如我们有一个Map对象,不断往里面放对象,实际的场景可能是这些对象不会再被使用到,这时候,这部分数据本身是垃圾的(因为不会再被使用),但实际上JVM会不会释放它(因为还被Map)引用着,这就是Java的内存泄露。
在开始分析之前,我们先想想,在编程这个角度上,我们如何避免堆内存泄露呢?实际上java.lang.ref这个包已经为我们提供了一种问题解决方案。Java的引用有4种:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、幻影引用(Phantom Reference),关于这部分介绍的文章一大批,此处就不做深入,我们只需要知道如下的信息:
强引用:除非将引用置为null,否则JVM不会对它垃圾,这是最常用的引用方式
软引用:在堆内存不足的时候,GC会将其垃圾回收
弱引用:每次GC都会将其垃圾回收
幻影引用:跟没有引用一样,每次获得的都是空的,没有太多使用的意义,仅是为了追踪对象在JVM的状态
一般对于大数据量的Cache信息或大对象,使用软引用/弱引用是一种非常好的习惯,或者至少使用一种淘汰算法,避免在堆内存拥挤大量的对象导致内存不足,如下是两个非常好的JDK默认提供的HashMap替代者:
org.apache.commons.collections.map.ReferenceMap:支持强引用/软引用和弱引用来存储key/value对
org.apache.commons.collections.map.LRUMap:可以控制总容量,采用LRU淘汰算法,将不常使用的数据淘汰出去
介绍完一些背景,我们开始进入主题。在开始分析之前,我们需要先dump下JVM的堆内存信息(虽然Eclipse Memory Analyzer直接attach到JVM上获取栈再分析,实际应用价值不大)
jmap –dump:file=test.bin {pid}
现在我们有了test.bin这个堆文件,使用Eclipse Memory Analyzer打开,分析完堆,我们可以选择“Leak Suspects Report”进行内存泄露分析。通过这个视图,我们可以大概得到内存泄露的初步结论
Historygram也是一个非常常用的视图,可以获得堆中对象的数据统计,有排序、过滤的功能,非常好用
Eclipse Memory Analyzer还包括如下功能:
在Historygram视图中右击对象弹出的功能框中,可以获得对象相互引用的关系的功能
Dominator Tree的视图采用Tree的方式来展现整个栈对象相互引用的情况
OQL视图支持使用OQL语言来查询对象信息
相关文章推荐
- android中JNI调用时内存分布以及内存泄露原因分析
- ArrayList 与HashSet的比较,及应用反射读取properties配置文件中的数据进行实例化再调用,以及类加载器的使用;还有HashCode的分析,及导致内存泄露,内存溢出的原因之一
- 用Eclipse Memory Analyzer查找内存泄露
- 《JVM故障诊断指南》之5 —— HPROF :使用Eclipse Memory Analyzer 工具 (MAT)进行内存泄露分析
- Java的内存管理,以及导致Java内存泄露的原因
- android 内存泄露原因以及排查和解决方案
- 内存泄露从入门到精通三部曲之三 :常见原因与用户实践
- 内存泄露从入门到精通三部曲之常见原因与用户实践
- 使用Eclipse Memory Analyzer进行内存泄漏分析三部曲
- Java内存泄露原因详解
- 使用Memory Analyzer Tool(MAT)Eclipse插件分析内存泄露
- Java垃圾回收机制以及内存泄露
- Eclipse中的快捷键快速生成常用代码(例如无参、带参构造,set、get方法),以及Java中重要的内存分析(栈、堆、方法区、常量池)
- 使用Eclipse Memory Analyzer进行内存泄漏分析三部曲
- Java垃圾回收机制以及内存泄露
- 引起内存泄露的原因:CheckList
- 内存泄露原因及解决方案
- 使用 Eclipse Memory Analyzer 检测内存泄漏问题
- win7开机报错“0x7ccaaa9b指令引用的内存”的原因以及解决方法
- android内存泄露的原因