用Java创建内存泄漏

我刚接受采访,并被要求用Java创建内存泄漏。 毋庸置疑,我对于如何开始创建一个自己而言毫无头绪。

一个例子会是什么?


以下是在纯Java中创建真正的内存泄漏(通过运行代码无法访问但仍保存在内存中的对象)的好方法:

  • 应用程序创建一个长时间运行的线程(或使用线程池来更快地泄漏)。
  • 线程通过一个(可选的自定义)ClassLoader加载一个类。
  • 该类分配一大块内存(例如, new byte[1000000] ),在静态字段中存储对它的强引用,然后将引用存储到ThreadLocal中。 分配额外的内存是可选的(泄露Class实例就足够了),但它会使泄漏工作更快。
  • 线程清除对自定义类或从其加载的ClassLoader的所有引用。
  • 重复。
  • 这是可行的,因为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