java - 如何在 Java 中创建内存泄漏?

标签 java memory memory-leaks

我刚刚接受了一次面试,我被要求用 Java 创建一个内存泄漏

不用说,我什至不知道如何开始创建一个,感觉很愚蠢。

有什么例子?

最佳答案

这是在纯 Java 中创建真正的内存泄漏(运行代码无法访问但仍存储在内存中的对象)的好方法:

  1. 应用程序创建一个长时间运行的线程(或使用线程池更快地泄漏)。
  2. 线程通过(可选自定义)ClassLoader加载一个类。
  3. 该类分配一大块内存(例如 new byte[1000000]),在静态字段中存储对它的强引用,然后在 中存储对自身的引用线程本地。分配额外的内存是可选的(泄漏类实例就足够了),但它会使泄漏工作得更快。
  4. 应用程序清除对自定义类或从中加载它的 ClassLoader 的所有引用。
  5. 重复。

由于 ThreadLocal 在 Oracle 的 JDK 中实现的方式,这会造成内存泄漏:

  • 每个Thread都有一个私有(private)字段threadLocals,它实际上存储了线程局部值。
  • 此映射中的每个 key 都是对 ThreadLocal 对象的弱引用,因此在该 ThreadLocal 对象被垃圾回收之后,它的条目已从 map 中移除。
  • 但每个都是强引用,所以当一个值(直接或间接)指向ThreadLocal对象时,即是它的key ,只要线程存在,该对象就不会被垃圾收集或从 map 中删除。

在本例中,强引用链如下所示:

Thread 对象 → threadLocals 映射 → 示例类的实例 → 示例类 → 静态 ThreadLocal 字段 → ThreadLocal对象。

(ClassLoader 并没有真正起到造成泄漏的作用,它只是因为这个额外的引用链而使泄漏变得更糟:example class → ClassLoader →它加载的所有类。在许多 JVM 实现中甚至更糟,尤其是在 Java 7 之前,因为类和 ClassLoader 被直接分配到 permgen 中,根本没有被垃圾回收。)

这种模式的一个变体是,如果您经常重新部署恰好使用 ThreadLocal 的应用程序(这些应用程序以某种方式指向自身),那么应用程序容器(如 Tomcat)可能会像筛子一样泄漏内存。发生这种情况的原因有很多,而且通常很难调试和/或修复。

更新:由于很多人一直要求它,here's some example code that shows this behavior in action .

关于java - 如何在 Java 中创建内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6470651/

相关文章:

c++ - 在内存泄漏等方面还可以吗

java - 如何从 Java 代码编写乐观和悲观锁定

java - 奇怪的数组返回类型

memory - 由于 openssl, ARM SIGILL 上的 valgrind

c - 摆脱基于文件的通信

C - 使用 open() 和 fdopen() 时关闭文件的正确方法

java - 搜索并替换没有大括号的 if 语句以包含大括号

java - super 关键字是否应该访问私有(private)字段和方法。我能够访问私有(private)方法和字段

java - 算法简单但内存不足

Python 2.7 内存泄漏与 scipy.minimize