本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看<活动链接>
提问:如何在Java中创建内存泄漏?
我刚刚接受面试,并被面试官要求使用Java来实现一次内存泄漏。
不用说,我对如何开始实现它一无所知。
能否给出一个例子?
回答之前先解释下内存泄漏
内存泄露本意是申请的内存空间没有被正确释放,导致后续程序里这块内存被永远占用(不可达),而且指向这块内存空间的指针不再存在时,这块内存也就永远不可达了
热门回答:
可以通过满足以下条件来实现内存泄漏:
- 创建一个长时间运行的线程(使用线程池泄露的速度更快)。
- 线程通过ClassLoader加载某个类(也可以用自定义ClassLoader)。
- 这个类分配了大量内存(例如new byte[1000000]),赋给静态字段存储对它的强引用,然后在ThreadLocal中存储对自身的引用。还可以分配额外的内存,这样泄漏的速度更快(其实只要泄漏Class实例就足够了)。
- 这个线程会清除所有自定义类及加载它的ClassLoader的引用。
- 重复执行。
由于该方法ThreadLocal是在Oracle的JDK中实现的,因此会造成内存泄漏:
- 每个Thread都有一个私有字段threadLocals,该字段实际上存储线程局部变量值。
- ThreadLocalMap中的每个key都是对ThreadLocal实例的弱引用,因此在对该ThreadLocal对象进行垃圾回收时,会从map中删除这一键值对
- 但每个值(线程要存的变量)本身又都是强引用,所以当一个值直接或间接指向ThreadLocal对象时,只要线程还存在,这个对象将永远不会被垃圾回收。