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

如何在Java中创建内存泄漏?,第1张

如何在Java中创建内存泄漏

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

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

由于该方法

ThreadLocal
是在Oracle的JDK中实现的,因此会造成内存泄漏:

  • 每个Thread都有一个私有字段
    threadLocals
    ,该字段实际存储线程局部值。
  • 该映射中的每个键都是对
    ThreadLocal
    对象的弱引用,因此在对该
    ThreadLocal
    对象进行垃圾回收之后,其条目将从映射中删除。
  • 但是每个值都是一个强引用,因此,当一个值(直接或间接)指向
    ThreadLocal
    作为其键的对象时,只要线程存在,该对象就不会被垃圾回收或从映射中删除。

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

Thread对象→

threadLocals
地图→示例类的实例→示例类→静态
ThreadLocal
字段→
ThreadLocal
对象。

ClassLoader
在创建泄漏中并没有真正起作用,它只是由于以下附加引用链而使泄漏更糟:示例类→→
ClassLoader
它已加载的所有类。在许多JVM实现中,甚至更糟,尤其是在之前Java 7,因为类和
ClassLoaders
是直接分配到
permgen
中的,并且根本不会被垃圾回收。)

这种模式的一个变种是,如果你频繁地重新部署碰巧使用

ThreadLocals
的应用程序,而应用程序容器(例如Tomcat)像sieve 那样以某种方式指向自身,那么它可以像筛子一样泄漏内存。发生这种情况的原因很多,通常很难调试和/或修复。

更新:由于很多人一直在要求它,因此以下示例代码展示了这种行为。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4929642.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-12
下一篇 2022-11-12

发表评论

登录后才能评论

评论列表(0条)

保存