我刚刚接受了一次采访,被要求用Java创建内存泄漏。
不用说,我觉得自己很傻,不知道如何开始创作。
什么样的例子?
我刚刚接受了一次采访,被要求用Java创建内存泄漏。
不用说,我觉得自己很傻,不知道如何开始创作。
什么样的例子?
当前回答
这里有一个非常简单的Java程序,它将耗尽空间
public class OutOfMemory {
public static void main(String[] arg) {
List<Long> mem = new LinkedList<Long>();
while (true) {
mem.add(new Long(Long.MAX_VALUE));
}
}
}
其他回答
您可以使用sun.misc.Unsafe类进行内存泄漏。事实上,这个服务类用于不同的标准类(例如java.nio类)。不能直接创建此类的实例,但可以使用反射来获取实例。
代码不会在EclipseIDE中编译-使用javac命令编译代码(编译期间,您会收到警告)
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class TestUnsafe {
public static void main(String[] args) throws Exception{
Class unsafeClass = Class.forName("sun.misc.Unsafe");
Field f = unsafeClass.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);
System.out.print("4..3..2..1...");
try
{
for(;;)
unsafe.allocateMemory(1024*1024);
} catch(Error e) {
System.out.println("Boom :)");
e.printStackTrace();
}
}
}
重叠侦听器是内存泄漏的一个很好的例子:对象被添加为侦听器。当不再需要对象时,对象的所有引用都为空。然而,忘记从侦听器列表中删除对象会使对象保持活动状态,甚至对事件做出响应,从而浪费内存和CPU。看见http://www.drdobbs.com/jvm/java-qa/184404011
不终止的线程(比如在其运行方法中无限期休眠)。即使我们丢失了对它的引用,它也不会被垃圾收集。您可以添加字段以使线程对象变大。
目前排名靠前的答案列出了更多的技巧,但这些似乎是多余的。
也许通过JNI使用外部本机代码?
使用纯Java,这几乎是不可能的。
但这是一种“标准”类型的内存泄漏,即您无法再访问内存,但它仍然属于应用程序。相反,您可以保留对未使用对象的引用,或者打开流而不关闭它们。
可能是潜在内存泄漏以及如何避免它的最简单示例之一,是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)?该引用可能会使一个巨大的对象保持活力。。。