文章目录
1 自定义类加载器
自定义类加载器只需要继承 java.lang.ClassLoader 类,该类有两个核心方法,一个是 loadClass(String, boolean),实现了双亲委派机制,还有一个方法是findClass,默认实现是空方法,所以我们自定义类加载器主要是重写findClass方法。
- 自定义类加载器MyClassLoader
package study.wyy.jvm.classLoader;
import java.io.FileInputStream;
public class MyClassLoader extends ClassLoader {
private String classPath;
public MyClassLoader(String classPath) {
this.classPath = classPath;
}
private byte[] loadByte(String name) throws Exception {
name = name.replaceAll("\\.", "/");
FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class");
int len = fis.available();
byte[] data = new byte[len];
fis.read(data);
fis.close();
return data;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] bytes = loadByte(name);
return defineClass(name,bytes,0,bytes.length);
} catch (Exception e) {
e.printStackTrace();
throw new ClassNotFoundException();
}
}
}
- 测试
- 定义一个目标类,使用我们的自定义加载器去加载
package study.wyy.jvm.model;
public class TargetClass {
void sayHello(){
System.out.println("say hello");
}
}
- idea编译之后,将这个类的class文件放到
/Users/wyaoyao/Documents/test
下
package study.wyy.jvm.classLoader;
public class MyClassLoaderTest {
public static void main(String[] args) throws Exception {
//初始化自定义类加载器,会先初始化父类ClassLoader,其中会把自定义类加载器的父加载器设置为应用程序类加载器AppClassLoader, 指定MyClassLoader加载的路径为/Users/wyaoyao/Documents/test
MyClassLoader classLoader = new MyClassLoader("/Users/wyaoyao/Documents/test");
//test目录创建 study.wyy.jvm.model 几级目录,将TargetClass类的class文件TargetClass.class丢入该目录
Class clazz = classLoader.loadClass("study.wyy.jvm.model.TargetClass");
System.out.println(clazz.getClassLoader().getClass().getName());
}
}
输出:
sun.misc.Launcher$AppClassLoader
为啥是AppClassLoader,而不是我们的MyClassLoader?
k理解了双亲委派机制,这个就很好理解了
- 我们自己定义的MyClassLoader,去加载的时候TargetClass,会先委派它的父加载器AppClassLoader去加载,这个时候AppClassLoader也能加载到(idea的target目录下也有这么一个class),既然父加载器AppClassLoader加载到,就会返回。所以是AppClassLoader
如何让MyClassLoader去加载呢
- 删除idea的target目录下的TargetClass.class,这样AppClassLoader就加载不到,就会交给MyClassLoader去加载/Users/wyaoyao/Documents/test这个目录下的TargetClass.class
是否对双亲委派机制有了比较感观的认识了!!!