我刚刚接受了一次采访,在面试中我被要求用Java创建一个内存泄漏。
不用说,我觉得自己很笨,根本不知道怎么开始创作。
举个例子怎么样?
发布于 2011-06-24 18:05:10
下面是在纯Java中创建真正内存泄漏(运行代码无法访问但仍存储在内存中的对象)的好方法:
ClassLoader加载类。new byte[1000000]),在静态字段中存储对它的强引用,然后在ThreadLocal中存储对自身的引用。分配额外的内存是可选的(泄漏类实例就足够了),但它会使泄漏工作得更快。ClassLoader的所有引用。由于在甲骨文的JDK中实现ThreadLocal的方式,这会造成内存泄漏:
Thread都有一个私有字段threadLocals,它实际上存储线程本地值。ThreadLocal对象的弱引用,因此在垃圾收集ThreadLocal对象之后,它的条目将从映射中删除。ThreadLocal对象时,只要线程存在,该对象就不会被垃圾收集,也不会从映射中移除。在本例中,强引用链如下所示:
Thread对象threadLocals映射示例类的→实例,→示例类,→静态ThreadLocal字段,→,ThreadLocal对象。
( ClassLoader在创建泄漏方面并没有真正发挥作用,它只会使泄漏更糟,因为有了这个额外的引用链:示例类→ClassLoader→,它加载的所有类。更糟糕的是,在许多JVM实现中,尤其是在Java 7之前,因为类和ClassLoader被直接分配到permgen中,从来没有垃圾收集过。)
这种模式的一个变化是,为什么应用程序容器(如Tomcat)会像筛子一样泄漏内存,如果您频繁地重新部署应用程序,而这些应用程序恰好使用ThreadLocal,在某种程度上指向了它们自己。这可能是由于许多微妙的原因造成的,而且通常很难调试和/或修复。
更新:因为很多人一直在要求它,下面是一些示例代码,它显示了这种行为的作用。
发布于 2011-07-01 13:33:55
保存对象引用的静态字段(特别是最终字段)
class MemorableClass {
static final ArrayList list = new ArrayList(100);
}(未关闭)开放流(文件、网络等)
try {
BufferedReader br = new BufferedReader(new FileReader(inputFile));
...
...
} catch (Exception e) {
e.printStackTrace();
}不闭连接
try {
Connection conn = ConnectionFactory.getConnection();
...
...
} catch (Exception e) {
e.printStackTrace();
}无法从JVM的垃圾收集器访问的区域,例如通过本机方法分配的内存。
在web应用程序中,某些对象存储在应用程序范围内,直到应用程序显式停止或删除为止。
getServletContext().setAttribute("SOME_MAP", map);不正确或不适当的JVM选项,例如IBM上的防止未使用类垃圾收集的noclassgc选项。
见IBM设置。
发布于 2011-06-24 16:16:29
要做的一件简单的事情是使用带有不正确(或不存在) HashSet或equals()的hashCode(),然后继续添加“重复”。而不是忽略重复的应该,集将永远只会增长,你将无法删除他们。
如果您希望这些坏的键/元素在周围徘徊,您可以使用一个静态字段,如
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.https://stackoverflow.com/questions/6470651
复制相似问题