我刚刚接受采访,并被要求使用Java 造成内存泄漏。 不用说,我对如何开始创建它一无所知。
一个例子是什么?
这是在纯Java中创建真正的内存泄漏(运行代码无法访问但仍存储在内存中的对象)的好方法:
ClassLoader
new byte[1000000]
ThreadLocal
由于该方法ThreadLocal是在Oracle的JDK中实现的,因此会造成内存泄漏:
threadLocals
在此示例中,强引用链如下所示:
Thread对象→ threadLocals地图→示例类的实例→示例类→静态ThreadLocal字段→ ThreadLocal对象。
(ClassLoader在创建泄漏中并没有真正起作用,它只是由于以下附加引用链而使泄漏更糟:示例类→→ ClassLoader它已加载的所有类。在许多JVM实现中,甚至更糟,尤其是在之前Java 7,因为类和ClassLoaders是直接分配到permgen中的,并且根本不会被垃圾回收。)
ClassLoaders
permgen
这种模式的一个变种是,如果你频繁地重新部署碰巧使用ThreadLocals的应用程序,而应用程序容器(例如Tomcat)像sieve 那样以某种方式指向自身,那么它可以像筛子一样泄漏内存。发生这种情况的原因很多,通常很难调试和/或修复。
ThreadLocals
更新:由于很多人一直在要求它,因此以下示例代码展示了这种行为。
静态字段保存对象参考[特别是最终字段]
class MemorableClass { static final ArrayList list = new ArrayList(100); }
调用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();
(未关闭)打开的流(file , network etc…)
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选项,例如noclassgc防止未使用的类垃圾回收的IBM JDK上的选项
noclassgc