在Java中,引用分为强引用、软引用、弱引用和虚引用四种。
- 强引用,代码中普遍存在的形式,例如常见的普通类new出对象后的引用。GC不会回收强引用的对象。
- 软引用,软引用对象会在内存溢出异常之前进行回收,也就是说在内存富裕的情况下GC不回收软引用。它可通过SoftReference类实现。
- 弱引用,弱引用对象会在下一次GC时被回收,也就是说不管内存富不富裕,当GC时都会回收弱引用。它可通过WeakReference类实现。
- 虚引用,虚引用不会改变对象的生存时间,它只是让对象在被GC时能收到一个系统通知。
了解了所有引用类型后看下如何基于弱引用对程序进行内存泄漏检测。
假如在你的程序中有某类的对象很可能会造成内存泄漏,姑且称为MaybeMemoryLeak类。内存泄漏就是虚拟机在做垃圾回收时某些“垃圾”由于某些原因而导致无法回收,每次实例化出来的对象都无法回收,最终导致内存爆了。也就是如果某些MaybeMemoryLeak应该被回收的对象无法回收,就会导致内存泄漏。
如果无法避免内存泄漏的可能性,那么如何检测内存泄漏现象呢?
这里就要用到上面所说的弱引用,它能很好判断MaybeMemoryLeak有没有被GC回收,被弱引用关联的对象只能生存到下一次垃圾回收发生之前,即如果某MaybeMemoryLeak对象只被某弱引用关联,则它会在下次垃圾回收时被回收,但如果MaybeMemoryLeak对象除了被弱引用关联外还被其他对象强引用,那么MaybeMemoryLeak对象是不会被回收的,根据这些条件就可以判断是否有MaybeMemoryLeak内存泄漏了。
在实际的实现中可以通过WeakHashMap来实现弱引用,只需将MaybeMemoryLeak对象put到WeakHashMap中,例如weakMap.put(“a”,maybeMemoryLeak),当maybeMemoryLeak及其包含的元素没有被其它任何类加载器中的元素引用到时,JVM发生垃圾回收时则会把maybeMemoryLeak对象回收,否则就将一直回收不了。
这里使用一个WeakHashMap用于追踪MaybeMemoryLeak对象,在查找内存泄漏之前要先强制调用System.gc();进行一次垃圾回收,保证没问题的MaybeMemoryLeak对象都被回收掉,这时可以查看WeakHashMap对象还存在哪些MaybeMemoryLeak对象,如果存在某些“垃圾”MaybeMemoryLeak对象,则属于内存泄漏。
====广告时间,可直接跳过====
鄙人的新书《Tomcat内核设计剖析》已经在京东预售了,有需要的朋友可以到 https://item.jd.com/12185360.html 进行预定。感谢各位朋友。
=========================
欢迎关注: