Class.forName(String className)使用哪个类加载器? 2015-01-08 20:56 2196人阅读 评论(0) 收藏 举报 分类: Java虚拟机(13) 版权

来源:互联网 发布:java A 编辑:程序博客网 时间:2024/05/18 00:10
转载自:http://blog.csdn.net/zhangzeyuaaa/article/details/42529591
 

Class.forName(String className)使用哪个类加载器?

 2196人阅读 评论(0) 收藏 举报
 分类:

不看源码,以为Class.forName(String className)使用的是系统类加载器,看了源码才知道不是这么回事。

[java] view plain copy
 print?
  1. public static Class<?> forName(String className)   
  2.                throws ClassNotFoundException {  
  3.        return forName0(className, true, ClassLoader.getCallerClassLoader());  
  4.    }  
通过 ClassLoader.getCallerClassLoader()获取类加载器:
[java] view plain copy
 print?
  1. // Returns the invoker's class loader, or null if none.  
  2.    // NOTE: This must always be invoked when there is exactly one intervening  
  3.    // frame from the core libraries on the stack between this method's  
  4.    // invocation and the desired invoker.  
  5.    static ClassLoader getCallerClassLoader() {  
  6.        // NOTE use of more generic Reflection.getCallerClass()  
  7.        Class caller = Reflection.getCallerClass(3);  
  8.        // This can be null if the VM is requesting it  
  9.        if (caller == null) {  
  10.            return null;  
  11.        }  
  12.        // Circumvent security check since this is package-private  
  13.        return caller.getClassLoader0();  
  14.    }  
看第一行注释,返回的是调用者的类加载器。显然,调用者的类加载器不一定是系统类加载器,比如我们使用了自定义类加载器。看下面的例子:

User.Java

[java] view plain copy
 print?
  1. package org.zzj;  
  2.   
  3. public class User {  
  4.   
  5. }  
UserService.java
[java] view plain copy
 print?
  1. package org.zzj;  
  2.   
  3. public class UserService {  
  4.     public void add() {  
  5.         try {  
  6.             System.out.println(Class.forName("org.zzj.User").getClassLoader());  
  7.         } catch (ClassNotFoundException e) {  
  8.             e.printStackTrace();  
  9.         }  
  10.     }  
  11. }  
ClassForNameTest.java
[java] view plain copy
 print?
  1. package org.zzj;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.lang.reflect.Method;  
  6.   
  7. public class ClassForNameTest {  
  8.     public static void main(String[] args) throws Exception {  
  9.         System.out.println(Class.forName("org.zzj.User").getClassLoader());  
  10.   
  11.         MyClassLoader classLoader = new MyClassLoader();  
  12.         Class<?> clazz = classLoader.loadClass("org.zzj.UserService");  
  13.         Method method = clazz.getMethod("add");  
  14.         method.invoke(clazz.newInstance());  
  15.     }  
  16. }  
  17.   
  18. class MyClassLoader extends ClassLoader {  
  19.     @Override  
  20.     public Class<?> loadClass(String name) throws ClassNotFoundException {  
  21.         String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";  
  22.         InputStream in = getClass().getResourceAsStream(fileName);  
  23.         if (in == null) {  
  24.             return super.loadClass(name);  
  25.         }  
  26.         byte[] b = null;  
  27.         try {  
  28.             b = new byte[in.available()];  
  29.             in.read(b);  
  30.             in.close();  
  31.         } catch (IOException e) {  
  32.             e.printStackTrace();  
  33.         }  
  34.         return defineClass(name, b, 0, b.length);  
  35.     }  
  36. }  
输出:
[plain] view plain copy
 print?
  1. sun.misc.Launcher$AppClassLoader@19821f  
  2. org.zzj.MyClassLoader@14318bb  
两次加载使用的不是同一个类加载器,而是调用者的类加载器。
阅读全文
0 0
原创粉丝点击