什么是打破双亲委派机制呢?
那么这里第一步,我们需要知道什么是双亲委派机制?
前面已经说了什么是双亲委派机制了,那打破是怎么回事呢?
比如,我现在有一个自定义类加载器,加载的是~/com/lxl/jvm/User1.class类,而在应用程序的target目录下也有一个com/lxl/jvm/User1.class, 那么,最终User1.class这个类将被哪个类加载器加载呢? 根据双亲委派机制,我们知道,他一定是被应用程序类加载器AppClassLoader加载,而不是我们自定义的类加载器,为什么呢? 因为他要向上寻找,向下委托. 当找到了以后,便不再向@R_404_424@了.
我们要打破双亲委派机制,就是要让自定义类加载器来加载我们的User1.class,而不是应用程序类加载器来加载
接下来分析,如何打破双亲委派机制呢? 双亲委派机制是在哪里实现的? 是在ClassLoader类的loadClass(...)方法实现的. 如果我们不想使用系统自带的双亲委派模式,只需要重新实现ClassLoader的loadClass(...)方法即可. 下面是ClassLoader中定义的loadClass()方法. 里面实现了双亲委派机制
下面给DefinedClassLoaderTest.java增加一个loadClass方法,拷贝上面的代码即可. 删除掉中间实现双亲委派机制的部分
这里需要注意的是,com.lxl.jvm是自定义的类包,只有我们自己定义的类才从这里加载. 如果是系统类,依然使用双亲委派机制来加载.
来看看运行结果:
源码:
package com.lxl.jvm; import java.io.FileInputStream; import java.lang.reflect.Method; /** * 自定义的类加载器 */ public class DefinedClassLoaderTest extends ClassLoader{ private String classPath; public DefinedClassLoaderTest(String classPath) { this.classPath = classPath; } * * 重写findClass方法 * * 如果不会写,可以参考URLClassLoader中是如何加载AppClassLoader和ExtClassLoader的 * @param name * @return * @throws ClassNotFoundException */ @Override protected Class<?> findClass(String name) throws ClassNotFoundException { try { byte[] data = loadBytes(name); return defineClass(name,data,0,data.length); } catch (Exception e) { e.printStackTrace(); } return null; } private byte[] loadBytes(String name) throws Exception { // 我们需要读取类的路径 String path = name.replace('.',1)">/').concat(".class"); String path = ""; 去路径下查找这个类 FileInputStream fileInputStream = new FileInputStream(classPath + " + path); int len = fileInputStream.available(); byte[] data = new [len]; fileInputStream.read(data); fileInputStream.close(); return data; } loadClass(String name,boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { First,check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == ) { * * 直接执行findClass()...什么意思呢? 首先会使用自定义类加载器加载类,不在向上委托,直接由 * 自己执行 * * jvm自带的类还是需要由引导类加载器自动加载 */ if (!name.startsWith(com.lxl.jvm)) { c = this.getParent().loadClass(name); } else { c = findClass(name); } } if (resolve) { resolveClass(c); } c; } } static void main(String[] args) throws Exception { DefinedClassLoaderTest classLoader = new DefinedClassLoaderTest(/Users/luoxiaoli); Class<?> clazz = classLoader.loadClass(com.lxl.jvm.User1); Object obj = clazz.newInstance(); Method sout = clazz.getDeclaredMethod(sout",); sout.invoke(obj,); System.out.println(clazz.getClassLoader().getClass().getName()); } }
原文链接:/jvm/997187.html