不看源码,以为Class.forName(String className)使用的是系统类加载器,看了源码才知道不是这么回事。
- public static Class<?> forName(String className)
- throws ClassNotFoundException {
- return forName0(className, true, ClassLoader.getCallerClassLoader());
- }
通过 ClassLoader.getCallerClassLoader()获取类加载器:
-
-
-
-
- static ClassLoader getCallerClassLoader() {
-
- Class caller = Reflection.getCallerClass(3);
-
- if (caller == null) {
- return null;
- }
-
- return caller.getClassLoader0();
- }
看第一行注释,返回的是调用者的类加载器。显然,调用者的类加载器不一定是系统类加载器,比如我们使用了自定义类加载器。看下面的例子:
User.Java
- package org.zzj;
-
- public class User {
-
- }
UserService.java
- package org.zzj;
-
- public class UserService {
- public void add() {
- try {
- System.out.println(Class.forName("org.zzj.User").getClassLoader());
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
- }
ClassForNameTest.java
- package org.zzj;
-
- import java.io.IOException;
- import java.io.InputStream;
- import java.lang.reflect.Method;
-
- public class ClassForNameTest {
- public static void main(String[] args) throws Exception {
- System.out.println(Class.forName("org.zzj.User").getClassLoader());
-
- MyClassLoader classLoader = new MyClassLoader();
- Class<?> clazz = classLoader.loadClass("org.zzj.UserService");
- Method method = clazz.getMethod("add");
- method.invoke(clazz.newInstance());
- }
- }
-
- class MyClassLoader extends ClassLoader {
- @Override
- public Class<?> loadClass(String name) throws ClassNotFoundException {
- String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
- InputStream in = getClass().getResourceAsStream(fileName);
- if (in == null) {
- return super.loadClass(name);
- }
- byte[] b = null;
- try {
- b = new byte[in.available()];
- in.read(b);
- in.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return defineClass(name, b, 0, b.length);
- }
- }
输出:
- sun.misc.Launcher$AppClassLoader@19821f
- org.zzj.MyClassLoader@14318bb
两次加载使用的不是同一个类加载器,而是调用者的类加载器。