用Java创建内存泄漏
我刚接受采访,并被要求用Java创建内存泄漏。 毋庸置疑,我对于如何开始创建一个自己而言毫无头绪。
一个例子会是什么?
以下是在纯Java中创建真正的内存泄漏(通过运行代码无法访问但仍保存在内存中的对象)的好方法:
new byte[1000000]
),在静态字段中存储对它的强引用,然后将引用存储到ThreadLocal中。 分配额外的内存是可选的(泄露Class实例就足够了),但它会使泄漏工作更快。 这是可行的,因为ThreadLocal保留对该对象的引用,该引用保持对其Class的引用,该引用继而保持对其ClassLoader的引用。 ClassLoader反过来保持对它所加载的所有类的引用。
(在许多JVM实现中,尤其是在Java 7之前,这种情况更糟糕,因为Classes和ClassLoader被直接分配到了permgen中,并且根本没有GC'd。但是,无论JVM如何处理类卸载,ThreadLocal仍然会阻止类对象被回收。)
这种模式的一个变种就是为什么应用程序容器(如Tomcat)会像筛子一样泄漏内存,如果您经常以任何方式重新部署恰巧使用ThreadLocals的应用程序。 (由于应用程序容器使用了所描述的线程,并且每次重新部署应用程序时都会使用新的ClassLoader。)
更新 :由于许多人不断询问它,下面是一些示例代码,显示了这种行为。
持有对象引用的静态字段[esp final field]
class MemorableClass {
static final ArrayList list = new ArrayList(100);
}
在冗长的String上调用String.intern()
String str=readString(); // read lengthy string any source db,textbox/jsp etc..
// This will place the string in memory pool from which you can't remove
str.intern();
(未封闭)开放流(文件,网络等)
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设置。
一个简单的事情就是使用一个带有不正确(或不存在) hashCode()
或equals()
的HashSet,然后继续添加“duplicates”。 不要忽略重复,因为它只会增长,你将无法删除它们。
如果你想让这些不好的键/元素挂起来,你可以使用类似的静态字段
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.
链接地址: http://www.djcxy.com/p/443.html
上一篇: Creating a memory leak with Java
下一篇: Improve INSERT