所属文集:ClassLoader串烧
关键字 Import , forName , loadClass 藕断丝连
问题:
通常我们都知道我们写的类,会被JVM加载,那都怎么被加载呢?
答案:
- 如果我们的类是
import
的方式(导入包,导入类)引入的,那么JVM自动帮我们去加载; - 另外一种情况是我们指定类加载器去加载;如使用
Class.forName(类名 ,指定的classLoader)
或者指定的classLoader.loadClass(xxx)
。
1.自动加载(import):
- 验证我们的代码中所使用(import导入)的类,在使用的时候会被
当前类加载器
自动加载,就是使用当前类加载器
的loadClass
方法。 -
当前类加载器
怎么理解, 当前类被哪个类加载器加载的,那么这个类加载器就叫做这个类的当前类加载器。那么这个类中通过import方式引入了其他类,就被JVM自动的调用当前类加载器的loadClass方法加载。
这个很好验证,ClassLoader的loadClass方法里自己打个断点,调试一下。
2.非自动加载:
非自动加载就是我们指定一个累加器去加载类,根据需要forName , loadClass二选一,问自己一个问题,forName是不是要遵守双亲委派模型?双亲委派的代码逻辑在ClassLoader#loadClass中,那是不是forName还会调用ClassLoader的loadClass的方法逻辑呢?会的
验证一下 接口:
public interface MsgCenter {
public boolean sendMsg(String msg);
}
实现
--
public class MsgValidater {
public boolean validate(String msg){
return true;
}
}
public class MsgCenterImpl implements MsgCenter {
@Override
public boolean sendMsg(String msg) {
// import MsgValidater类型
return new MsgValidater().validate(msg);
}
}
测试:
1.appClassLoader 加载接口
2.子加载器,forName方式加载实现类
- 实现类实例化,并赋值给接口类.调用sendMsg方法,此方法内引用了MsgValidater类.
/**
* 把MsgCenterImpl.class 移动到子加载器的加载路径中.保证只有子加载器可加载.
*/
@Test
public void testImportLoadClass(){
CustomClassLoader01 customClassLoader01 = new CustomClassLoader01(ClassLoader.getSystemClassLoader());
try {
//appClassloader 加载 接口
MsgCenter msgCenter = null;
//子加载器,加载 实现类
Class<?> aClass = Class.forName("com.rock.MsgCenterImpl",false,customClassLoader01);
//赋值 接口 = 实现类 ;这是可以的,因为子加载器可见父加载器所加载的类.
msgCenter =(MsgCenter)aClass.newInstance();
boolean hello = msgCenter.sendMsg("hello");
System.out.println("after sendMsg");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
输入结果
CustomClassLoader start load class :com.rock.MsgCenterImpl ; resolve : false
CustomClassLoader findLoadedClass : null
CustomClassLoader getParent().loadClass(name) : ClassNotFoundException
CustomClassLoader loadClassData : com.rock.MsgCenterImpl
//以上信息说明:forName方法通过自定义类加载器的loadClass方法加载了com.rock.MsgCenterImpl
CustomClassLoader start load class :com.rock.MsgCenter ; resolve : false
CustomClassLoader findLoadedClass : null
CustomClassLoader start load class :java.lang.Object ; resolve : false
CustomClassLoader findLoadedClass : null
//以上信息说明:子加载器 委托父加载器加载 com.rock.MsgCenter ,java.lang.Object
CustomClassLoader start load class :com.rock.classLoader.MsgValidater ; resolve : false
CustomClassLoader findLoadedClass : null
CustomClassLoader getParent().loadClass(name) : ClassNotFoundException
CustomClassLoader loadClassData : com.rock.classLoader.MsgValidater
//以上信息说明:自加载器加载了com.rock.classLoader.MsgValidater
after sendMsg
//以上信息说明,实现类赋值给接口后,调用接口的方法执行成功.

命名空间

网友评论