《Effective Java》消除过期的引用

引用书中的例子代码
《Effective Java》消除过期的引用
《Effective Java》消除过期的引用
这段代码是有内存泄漏的隐患的,主要原因在pop()方法,pop()方法将一个元素从栈中弹出后,虽然size减少了,但是elements[]数组还持有着弹出元素的引用,从而引发内存泄漏。

解决办法是可以手动将这个元素的引用置为null。
《Effective Java》消除过期的引用

显然在写代码的时候不可能一直关注着引用,发现不用就置为null,这是不可取的,那么在什么时候应该注意引用的手动释放(也就是置为null)呢?作者给出的答案是,在需要自己管理内存的时候,比如栈这样的数据结构。

ThreadLocal也有可能出现内存泄漏的问题,ThreadLocal内部维护了一个ThreadLocaMap的静态内部类,ThreadLocal通过空间换时间的方式完成了线程间的隔离,ThreadLocalMap内部有个Entry静态内部类,存放了ThreadLocal类型的key和Object类型的value,如果ThreadLocal对象被回收,value是无法被回收的,ThreadLocal在设计的时候考虑到了这一点,在get()方法、set()方法、remove()方法都显示的将该引用置为null,同时使用了WeakRefrence来,该引用只能生存到下一次垃圾回收,value可以在下一次get()/set()/remove()的时候释放。不可以单纯的依赖WeakRefrence,比如线程池会一直持有下去导致内存泄漏,所以在使用ThreadLocal完毕后一定要手动释放remove(),就像ReentrantLock一样,使用完要释放锁,关于ThreadLocal详细内容这里不详细展开,大家有兴趣的话可以自行搜索。

缓存的场景也容易发生内存泄漏,比如在类的初始化的时候创建了一些缓存,这些缓存很容易被人遗忘掉,可以自己通过WeakRefrence或者定时任务自定义策略去把控。

总结:在开发中要特别注意防止代码发生内存泄漏,内存泄漏的原因往往是很难排查的,有时会依靠一些分析工具,最好的解决办法就是将问题在发生前扼杀。