用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.
上一篇: Creating a memory leak with Java
下一篇: Improve INSERT
