JVM自带的类加载机制如下图,当你使用自定义的加载器进行加载时它会由上自下从custom加载器到APP加载器再到Ext加载器,最后到BootStrap加载器的缓存中查询是否有对应的类,如果都没有找到再依次再由上自下从文件中加载对应的类。这么做保证了类加载的安全,但是如果我们不想按JVM规定的这个流程走该怎么办呢,接下来我将介绍打破双亲委派的类加载机制。
第一步:创建自己的加载器并继承ClassLoader
private static class MyLoader extends ClassLoader {
//重写loadClass方法
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
//到对应的路径获取类
File f = new File("C:/work/ijprojects/JVM/out/production/JVM/" + name.replace(".", "/").concat(".class"));
//如果类不存在则调用父类加载器
if(!f.exists()) return super.loadClass(name);
//如果存在则自己加载对应的类
try {
InputStream is = new FileInputStream(f);
byte[] b = new byte[is.available()];
is.read(b);
return defineClass(name, b, 0, b.length);
} catch (IOException e) {
e.printStackTrace();
}
return super.loadClass(name);
}
}
第二步:使用自定义加载器进行加载
整体的思路就是先创建一个加载器先加载一遍然后再给创建一个新的加载器,再加载一遍,这样加载的类就是不同的类了。
public static void main(String[] args) throws Exception {
MyLoader m = new MyLoader();
Class clazz = m.loadClass("com.test.jvm.Hello");
m = new MyLoader();
Class clazzNew = m.loadClass("com.test.jvm.Hello");
System.out.println(clazz == clazzNew);
}