kuangbaoxu 发表于 2013-1-27 05:17:16

classloader 总结

classloader对我来说一直都是很神秘的东东,这两天一直在研究,总算搞清楚了一些概念。现在写出来作为一个纪录。
classloader利用一种叫双亲委派的方法来加载类,也就是先让该classloader的parent来加载。具体的parent关系我就不再废话了。代码如下:
Java代码
   protected synchronized Class<?> loadClass(String name, boolean resolve)   throws ClassNotFoundException      {   // First, check if the class has already been loaded   Class c = findLoadedClass(name);   if (c == null) {       try {       if (parent != null) {         c = parent.loadClass(name, false);       } else {         c = findBootstrapClass0(name);       }       } catch (ClassNotFoundException e) {         // If still not found, then invoke findClass in order         // to find the class.         c = findClass(name);       }   }   if (resolve) {       resolveClass(c);   }   return c;      }      protected synchronized Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException    {// First, check if the class has already been loadedClass c = findLoadedClass(name);if (c == null) {    try {if (parent != null) {    c = parent.loadClass(name, false);} else {    c = findBootstrapClass0(name);}    } catch (ClassNotFoundException e) {      // If still not found, then invoke findClass in order      // to find the class.      c = findClass(name);    }}if (resolve) {    resolveClass(c);}return c;    }当然,虽然加载时候有parent关系,但实际上这些classloader不一定有java语义上的继承关系(或者说不必须)。
另外就是:名字空间的问题,我认为这个名字空间可以认为由两部分构成,一部分是包名,另一部分是classloader对象。也就是说:如果两个类属于同一个包下,但是由不同的classloader加载,那么他们的也不能互访default类型方法、属性。代码如下:
Java代码
public class LoaderSample2 {       public static void main(String[] args) {         try {               AutoResolveClassLoader loader = new AutoResolveClassLoader();   //          ClassLoader loader = LoaderSample2.class.getClassLoader();               Class c = loader.loadClassInMyWay("com.cxz.cl.LoaderSample3", true);   //          Class c = loader.loadClass("com.cxz.cl.LoaderSample3");               Object o = c.newInstance();               System.out.println(c.getClassLoader() == LoaderSample2.class.getClassLoader());//如果你的classloader仅仅重写了findclass这个会打印true,因此两个类被同一个classloader加载,而不会出现预期结果。所以你需要重写一个loadClassInYourWay方法来加载。               Field f = c.getDeclaredField("age");//c.getField("age");               int age = f.getInt(o);               System.out.println("age is " + age);         } catch (Exception e) {               e.printStackTrace();         }       }   }public class LoaderSample2 {public static void main(String[] args) {try {AutoResolveClassLoader loader = new AutoResolveClassLoader();//ClassLoader loader = LoaderSample2.class.getClassLoader();Class c = loader.loadClassInMyWay("com.cxz.cl.LoaderSample3", true);//Class c = loader.loadClass("com.cxz.cl.LoaderSample3");Object o = c.newInstance();System.out.println(c.getClassLoader() == LoaderSample2.class.getClassLoader());//如果你的classloader仅仅重写了findclass这个会打印true,因此两个类被同一个classloader加载,而不会出现预期结果。所以你需要重写一个loadClassInYourWay方法来加载。Field f = c.getDeclaredField("age");//c.getField("age");int age = f.getInt(o);System.out.println("age is " + age);} catch (Exception e) {e.printStackTrace();}}}LoaderSample2和LoaderSample3是同一个包下的类,如果由同一个classloader加载,则通过反射获得LoaderSample3.age属性是可行的(该属性的类型时default)如果利用我自己写的一个classloader加载,则由于classloader不同,则不能访问该age属性。 值得注意的是,如果你建立你自己的classloader,javadoc中建议override findclass方法,但是再loadclass的过程中还会采取双亲委派的模式,也就是说,不能把你要加载的class防到classpath中,否则jvm还会利用appclassloader来加载。我就是采用重新写了一个loadClassInMyWay方法,消除双亲委派。具体代码如下: Java代码 public synchronized Class loadClassInMyWay(String name, boolean resolve)         throws ClassNotFoundException {       // First, check if the class has already been loaded       Class c = findLoadedClass(name);       if (c == null) {         c = this.findClass(name);//该方法由我override       }       return c;   }public synchronized Class loadClassInMyWay(String name, boolean resolve)throws ClassNotFoundException {// First, check if the class has already been loadedClass c = findLoadedClass(name);if (c == null) {c = this.findClass(name);//该方法由我override}return c;}其中然我很迷惑的一点是:如果我单纯的override方法:loadClass,运行时刻会给我报异常ClassCircularityError不明白为什么~

以下摘自ibm网站,具体网址:https://www6.software.ibm.com/developerworks/cn/education/java/j-classloader/tutorial/j-classloader-2-2.shtml
总结classloader的通常作用:
* 在执行非置信代码之前,自动验证数字签名
* 使用用户提供的密码透明地解密代码
* 动态地创建符合用户特定需要的定制化构建类
页: [1]
查看完整版本: classloader 总结