我刚刚接受了一次采访,被要求用Java创建内存泄漏。
不用说,我觉得自己很傻,不知道如何开始创作。
什么样的例子?
我刚刚接受了一次采访,被要求用Java创建内存泄漏。
不用说,我觉得自己很傻,不知道如何开始创作。
什么样的例子?
当前回答
Swing使用对话框非常简单。创建一个JDialog,显示它,用户关闭它,然后泄漏!
您必须调用dispose()或配置setDefaultCloseOperation(dispose_ON_CLOSE)。
其他回答
可能是潜在内存泄漏以及如何避免它的最简单示例之一,是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)?该引用可能会使一个巨大的对象保持活力。。。
创建一个静态映射并不断添加硬引用。这些永远不会被垃圾收集。
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); }
}
内存泄漏是一种资源泄漏,当计算机程序错误地管理内存分配,导致不再需要的内存无法释放时,就会发生这种情况=>维基百科定义
这是一种相对基于上下文的主题,你可以根据自己的喜好创建一个主题,只要未使用的引用永远不会被客户使用,但仍然存在。
第一个例子应该是一个自定义堆栈,而不取消有效Java第6项中过时的引用。
当然,只要你愿意,还有很多,但如果我们看看Java内置类,它可能是
子列表()
让我们检查一些超级愚蠢的代码来产生泄漏。
public class MemoryLeak {
private static final int HUGE_SIZE = 10_000;
public static void main(String... args) {
letsLeakNow();
}
private static void letsLeakNow() {
Map<Integer, Object> leakMap = new HashMap<>();
for (int i = 0; i < HUGE_SIZE; ++i) {
leakMap.put(i * 2, getListWithRandomNumber());
}
}
private static List<Integer> getListWithRandomNumber() {
List<Integer> originalHugeIntList = new ArrayList<>();
for (int i = 0; i < HUGE_SIZE; ++i) {
originalHugeIntList.add(new Random().nextInt());
}
return originalHugeIntList.subList(0, 1);
}
}
实际上,还有另一个技巧,我们可以利用HashMap的查找过程,使用HashMap造成内存泄漏。实际上有两种类型:
hashCode()始终相同,但equals()不同;使用随机hashCode()和equals()始终为true;
Why?
hashCode()->bucket=>equals()来定位该对
我打算先提到substring(),然后再提到subList(),但这个问题似乎已经解决了,因为它的源代码在JDK8中。
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
这很简单:
Object[] o = new Object[]{};
while(true) {
o = new Object[]{o};
}
我认为还没有人说过这一点:你可以通过重写finalize()方法来复活一个对象,这样finalize)就可以在某个地方存储对它的引用。垃圾回收器只会在对象上调用一次,因此在此之后,对象将永远不会被销毁。