首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Java中创建内存泄漏?

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

Stack Overflow用户
提问于 2011-06-24 16:11:52
回答 56查看 727.8K关注 0票数 3.6K

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

不用说,我觉得自己很笨,根本不知道怎么开始创作。

举个例子怎么样?

EN

回答 56

Stack Overflow用户

回答已采纳

发布于 2011-06-24 18:05:10

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

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

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

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

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

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

( ClassLoader在创建泄漏方面并没有真正发挥作用,它只会使泄漏更糟,因为有了这个额外的引用链:示例类→ClassLoader→,它加载的所有类。更糟糕的是,在许多JVM实现中,尤其是在Java 7之前,因为类和ClassLoader被直接分配到permgen中,从来没有垃圾收集过。)

这种模式的一个变化是,为什么应用程序容器(如Tomcat)会像筛子一样泄漏内存,如果您频繁地重新部署应用程序,而这些应用程序恰好使用ThreadLocal,在某种程度上指向了它们自己。这可能是由于许多微妙的原因造成的,而且通常很难调试和/或修复。

更新:因为很多人一直在要求它,下面是一些示例代码,它显示了这种行为的作用

票数 2.6K
EN

Stack Overflow用户

发布于 2011-07-01 13:33:55

保存对象引用的静态字段(特别是最终字段)

代码语言:javascript
复制
class MemorableClass {
    static final ArrayList list = new ArrayList(100);
}

(未关闭)开放流(文件、网络等)

代码语言:javascript
复制
try {
    BufferedReader br = new BufferedReader(new FileReader(inputFile));
    ...
    ...
} catch (Exception e) {
    e.printStackTrace();
}

不闭连接

代码语言:javascript
复制
try {
    Connection conn = ConnectionFactory.getConnection();
    ...
    ...
} catch (Exception e) {
    e.printStackTrace();
}

无法从JVM的垃圾收集器访问的区域,例如通过本机方法分配的内存。

在web应用程序中,某些对象存储在应用程序范围内,直到应用程序显式停止或删除为止。

代码语言:javascript
复制
getServletContext().setAttribute("SOME_MAP", map);

不正确或不适当的JVM选项,例如IBM上的防止未使用类垃圾收集的noclassgc选项。

IBM设置

票数 1.3K
EN

Stack Overflow用户

发布于 2011-06-24 16:16:29

要做的一件简单的事情是使用带有不正确(或不存在) HashSet或equals()hashCode(),然后继续添加“重复”。而不是忽略重复的应该,集将永远只会增长,你将无法删除他们。

如果您希望这些坏的键/元素在周围徘徊,您可以使用一个静态字段,如

代码语言:javascript
复制
class BadKey {
   // no hashCode or equals();
   public final String key;
   public BadKey(String key) { this.key = key; }
}

Map map = System.getProperties();
map.put(new BadKey("key"), "value"); // Memory leak even if your threads die.
票数 497
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6470651

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档