JDK中ClassLoader默认设计模式
分类
- BootStrap ClassLoader(启动ClassLoader)
- Extension ClassLoader (扩展ClassLoader)
- App ClassLoader (应用ClassLoader/系统ClassLoader)
- Custom ClassLoader(自定义ClassLoader)
具体加载对象
- 自底向上检查类是否已经加载,加载了就直接获取类
- 自顶向下尝试加载
- 防止了重复加载和核心类被篡改
代码实现:
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException{
synchronized (getClassloadingLock(name)){
// 查看是否已经被加载了
Class c = findLoadedClass(name);
// 没有被加载
if (c == null){
long t0 = System.nanoTime();
try{
if (parent != null){
// 请求父类去加载
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (classNotFoundException e){
...
}
}
所存在的问题
顶层ClassLoader,无法加载底层ClassLoader的类,启动ClassLoader无法加载生成App ClassLoader的实例对象。这就导致Bootstrap ClassLoader无法看到下层中的内容。
解决方法
Thread.setContextClassLoader()
- 上下文加载器
- 是一个
角色
【根据应用场景来设置】 - 用以解决顶层ClassLoader无法访问底层ClassLoader的类问题
- 基本思想是:在顶层ClassLoader中,传入底层ClassLoader的实例
双亲模式的破坏
- Tomcat的WebappClassLoader会先加载自己的Class,找不到再委托parent:保证公用的一起加载,私有的自己加载
protected synchronized Class<?> boadClass(String name, boolean resovle) throws ClassNotFoundException{
// 检查该类是否已经被加载&尝试自己加载
Class re = findClass(name);
if (re == null){ // 没有加载成功
System.out.Println("无法载入类:" + name + "需要请求父类加载");
// 交给父类进行加载
return super.loadClass(name, resolve);
}
return re;
}
protected Class<?> findClass(String className) throws ClassNotFoundException {
// 判断是否加载--防止重复加载
Class clazz = this.findLoadedClass(className);
if (null == clazz) {
try {
String classFile = getClassFile(className);
FileInputStream fis = new FileInputStream(classFile);
FileChannel fileC = fis.getChannel();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableByteChannel outC = Channels.newChannel(baos);
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
// 省略部分代码
fis.close();
byte[] bytes = baos.toByteArray();
// 自己去加载该类
clazz = defineClass(className, bytes, 0, bytes.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return clazz;
}
- OSGI的ClassLoader形成网状结构,根据需要自由加载Class:热加载