2016-08-22 83 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

相关问题