2012-12-19 46 views
12

我有孩子第一UrlClassLoader動態加載jar文件。然後我做一個反射來調用加載的jar文件中的一個方法。一旦完成,我寧願卸載類加載器。然後我嘗試做一些壓力測試代碼,以確保我的代碼運行順利。基本上,我試圖做的是在循環語句中加載和卸載jar。這裏是我的代碼:JDK1.7 ClassLoader內存泄漏

for (int i = 0; i < 1000; i++) { 
     //Just to show the progress 
     System.out.println("LOAD NUMBER : " + i); 

     ChildFirstURLClassLoader classLoader = null; 
     try { 
      File file = new File("C:\\library.jar"); 
      String classToLoad = "com.test.MyClass"; 
      URL jarUrl = new URL("file:" + file.getAbsolutePath()); 

      classLoader = new ChildFirstURLClassLoader(new URL[] {jarUrl}, null); 
      Class<?> loadedClass = classLoader.loadClass(classToLoad); 
      Method method = loadedClass.getDeclaredMethod("execute", 
        new Class[] {}); 

      ClassLoader currCl= Thread.currentThread().getContextClassLoader(); 
      Thread.currentThread().setContextClassLoader(classLoader); 
      method.invoke(null); 
      Thread.currentThread().setContextClassLoader(currCl); 

      method = null; 
      loadedClass = null; 
     } finally { 
      if (classLoader != null) { 
       classLoader.close(); 
       classLoader = null; 
      } 
     } 
    } 

當我JDK1.6下運行這段代碼,無需classLoader.close();聲明,該代碼運行完美。但是當我轉換成JDK1.7時,有時會出現java.lang.OutOfMemoryError: PermGen space錯誤。不幸的是它以不一致的方式出現。

+2

您可以嘗試設置最大燙髮代碼,以查看這種情況是否發生在更低值的情況下。如果沒有發生,您還可以檢查Java 6的最大值是否相同。 –

+3

你的com.test.MyClass類是做什麼的? Java 7中發生了一些變化,因此掛起的finalize方法可能會阻止類被釋放,也許這就是您在這裏看到的問題。在OutOfMemory上創建堆轉儲,將其加載到MemoryAnalyzer(或類似工具),列出類加載器並搜索對它們的引用。 – mihi

+0

謝謝你彼得和Mihi,我試圖增加最大permgen,但它仍然是一樣的。在Java 6中,我只用64m permgen空間運行沒有問題。實際上,com.test.MyClass通過使用Spring JDBC查詢數據庫。我已經分析了我的堆轉儲,並且看到沒有強類型引用到類加載器中。謝謝大家。 – user1915918

回答

2

確定泄漏來自哪裏的最簡單方法是使用分析器來監視內存使用情況。試試JProfiler或VisualVM。它將使您能夠確定泄漏的確切位置,併爲您提供有關是否以及如何修復泄漏的線索。