INTRO
- 称为存储渗漏。
- 严格来说,当对象不会被用到了,但Garbage Collector不能回收,称为内存泄露。
- 很多情况是,由于使用不当,导致对象的生命周期变得很长,甚至导致Out of Memory,称为宽泛意义上的内存泄露

分类
- 经常发生:泄露的代码会被多次执行
- 偶尔发生:某些特定情况下才会发生
- 一次性:代码只执行一次
- 隐式泄露:一直占着内存不释放,直到执行结束
内存泄露与内存溢出的关系
内存泄露的情况
- 静态集合集
- static 标记的 HashMap LinkedList
- 生命周期与JVM一致
- 在程序结束之前不能被释放
- 长生命周期的对象,持有短生命周期对象的引用,导致短生命周期的对象无法被回收
- 单例模式
- 单例是指一个类只有一个实例化对象
- 因此这个对象与类是相互绑定的关系
- 是静态的
- 生命周期与JVM一致
- 内部类持有外部类
- 内部类被长期引用
- 内部类归属于外部类
- 因此,即使外部类不再被使用,也不能被回收
- 各种连接,数据库连接,网络连接,IO连接
- 这些连接如果没有被关闭的话,垃圾回收器不会回收其对象
- 数据库一般会维持一个大小恒定的连接池
- 变量不合理的作用域
- 变量的作用范围大于其使用范围
- 导致某些不该存在的变量在内存中多存活一段时间
- 改变哈希值
- 一个对象被存储进HashSet中,不能修改参与哈希值计算的字段
- 否则对象修改后的hash值,和set中的hash不一致
- 使用当前对象去检索,在set中将检索不到
- 因此,如果修改前的对象丢失,很容易造成HashSet中对象不能检索和删除
- 造成内存泄露
- 缓存泄露
- 当你把对象放进缓存中时,很容易遗忘他
- 可以使用WeakHashMap代替缓存
- 当map中的key没有其他refernece时,会自动丢弃此key
- 监听器和回调
- 回调函数:主函数执行完,再执行穿参进来的回调函数
- 回调函数如果没有被显示的取消,仍然会占用内存
- 可以使用WeakHashMap存他的弱引用
如何定位内存泄露
- 主要命令
jstack 生成虚拟机中所有线程的快照 一般用于CPU 100%
jmap 生成堆转储快照
jmap -dump:format=b, file={path}{pid}
- 利用
mat分析dump文件
mat Memory Analyzer Tool
- JVM常用命令
- jps
- jstat
- jinfo
- jmap
- jstack
- jhat
- JVM性能检测工具
- Eclipse Memory Analyzer
- JProfile
- JProbe Profiler
- JVisualVM
- JConsole
- Plumbr
- 引用一个分析BLOG。