java - 如何在 Java 中造成内存泄漏?

标签 java memory memory-leaks

我刚刚接受了一次采访,被要求用 Java 创建内存泄漏

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

举个例子是什么?

最佳答案

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

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

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

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

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

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

(ClassLoader 在创建泄漏方面并没有真正发挥作用,它只是因为这个额外的引用链而使泄漏变得更糟:示例类 → 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/17160737/

相关文章:

python - 使用 python 运行未导出的 .dll 函数

c# - 从另一个 WCF 服务中调用 WCF 服务时发生 WCF 内存泄漏

c++ - VS2017 中的_crtBreakAlloc

java - 更改 AlertDialog 的背景

java - 需要正则表达式替换字符串中第一组括号之间的所有字符

java - 尝试启动 Firebase Java 客户端

C++内存地址和偏移写/读

java - Worklight 项目在构建时出现内存不足错误

azure - 对 Azure 网站上的(托管)内存泄漏进行故障排除

java - 使用 Volley 库访问 JSON 数组的嵌套项目