我刚刚接受了一次采访,被要求用Java创建内存泄漏。
不用说,我觉得自己很傻,不知道如何开始创作。
什么样的例子?
我刚刚接受了一次采访,被要求用Java创建内存泄漏。
不用说,我觉得自己很傻,不知道如何开始创作。
什么样的例子?
当前回答
创建一个静态映射并不断添加硬引用。这些永远不会被垃圾收集。
public class Leaker {
private static final Map<String, Object> CACHE = new HashMap<String, Object>();
// Keep adding until failure.
public static void addToCache(String key, Object value) { Leaker.CACHE.put(key, value); }
}
其他回答
创建一个只包含while true循环的JNI函数,并用另一个线程的大型对象调用它。GC不太喜欢JNI,并且会将对象永久保存在内存中。
可能是潜在内存泄漏以及如何避免它的最简单示例之一,是ArrayList.remove(int)的实现:
public E remove(int index) {
RangeCheck(index);
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index + 1, elementData, index,
numMoved);
elementData[--size] = null; // (!) Let gc do its work
return oldValue;
}
如果您是自己实现的,您是否想过清除不再使用的数组元素(elementData[-size]=null)?该引用可能会使一个巨大的对象保持活力。。。
保存对象引用的静态字段(尤其是最终字段)
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 JDK上的noclassgc选项,它阻止未使用的类垃圾收集
请参阅IBM JDK设置。
正如许多人所建议的那样,资源泄漏很容易造成,就像JDBC示例一样。实际的内存泄漏有点困难——尤其是如果您不依赖JVM中的碎片来为您进行泄漏。。。
创建占地面积非常大的对象,然后无法访问这些对象的想法也不是真正的内存泄漏。如果没有东西可以访问它,那么它将被垃圾收集,如果有东西可以访问,那么它就不是泄漏。。。
然而,一种曾经有效的方法——我不知道它是否仍然有效——是有一条三深的环形链。正如在对象A中有对对象B的引用,对象B有对对象C的引用,而对象C有对对象A的引用。GC足够聪明,知道如果A和B不能被任何其他对象访问,但不能处理三方链,则可以安全地收集两个深链(如在A<-->B中)。。。
也许通过JNI使用外部本机代码?
使用纯Java,这几乎是不可能的。
但这是一种“标准”类型的内存泄漏,即您无法再访问内存,但它仍然属于应用程序。相反,您可以保留对未使用对象的引用,或者打开流而不关闭它们。