2016-08-22 69 views
1

我想模擬元空間OOM。我計劃在不同的URLClassLoader加載ClassA類,這裏是代碼:爲什麼class不能被URLClassLoader加載?

package classloader; 

import java.io.File; 
import java.net.URL; 
import java.net.URLClassLoader; 
import java.util.ArrayList; 
import java.util.List; 

class ClassA { 
    public void method(String input){} 
} 

public class ClassMetadataLeakSimulator { 
    private final static int NB_ITERATIONS_DEFAULT = 50000; 

    public static void main(String[] args) { 
     System.out.println("Class metadata leak simulator"); 
     int nbIterations = (args != null && args.length == 1) ? Integer.parseInt(args[0]) : NB_ITERATIONS_DEFAULT; 
     try { 
      List<ClassLoader> list = new ArrayList<>(); 
      URL url = new File(".").toURI().toURL(); 
      URL[] urls = new URL[]{url}; 
      System.out.println(url); 
      for (int i = 0; i < nbIterations; i++) { 
       URLClassLoader newClassLoader = new URLClassLoader(urls); 
       list.add(newClassLoader); 
       newClassLoader.loadClass("classloader.ClassA"); 
      } 
     } 
     catch (Throwable any) { 
      System.out.println("ERROR: " + any); 
     } 
     System.out.println("Done!"); 
    } 
} 

不過,很奇怪的是,加載的類號停止時,它達到1437這是在jvisualvm顯示,和元空間大小所用的是低增長,即使for循環運行了數百萬次。看來ClassA並未被每個新的URLClassLoader實例加載。爲什麼?

回答

1

問題是URLClassLoader是由系統類加載器編寫的。首先,它會嘗試獲得類from parent classloader。所以,類只會被加載一次,你不會得到metaspace OOM。

您需要一個獨立的類加載器來完成這項工作。另一種選擇是使用cglibasm庫隨時生成類。

而且loadClass接受不規範二進制類名。

+0

我是ClassLoader中的新人,有沒有關於自定義ClassLoader的例子?我的意思是如何創建一個獨立的類加載器? – expoter

+0

@expoter在分離的類加載器上有一個基本的howto - http://blog.markturansky.com/archives/21 – vsminkov

+0

@expoter但我想這會更容易生成類。看看cglib增強器類。 – vsminkov