java实现自定义类加载器

互联网 20-10-28

各类加载器虽然以父子相称,但是没有继承关系

(视频教程推荐:java课程)

点入ClassLoader的源码查看样例:

* <blockquote><pre>  *     class NetworkClassLoader extends ClassLoader {  *         String host;  *         int port;  *  *         public Class findClass(String name) {  *             byte[] b = loadClassData(name);  *             return defineClass(name, b, 0, b.length);  *         }  *  *         private byte[] loadClassData(String name) {  *             // load the class data from the connection  *             &nbsp;.&nbsp;.&nbsp;.  *         }  *     }  * </pre></blockquote>

只需继承CalssLoader,重写 findClass方法即可:

package reflect;   import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List;   public class MyClassLoader extends ClassLoader{       // 用于保存加载的文件的大小     private int classSize;      // 新增的类加载路径     private static List<String> paths = new ArrayList<>();       static {         paths.add("D:\\Users\\jeff.chan\\Desktop\\");     }     // 默认会将app类加载器做为该类加载器的父加载器     public MyClassLoader() {     }       public MyClassLoader(ClassLoader parent) {         super(parent);     }       @Override     protected Class<?> findClass(String name) throws ClassNotFoundException {         byte[] b = loadBinaryData(name);         // 打印执行标记         System.out.println("use custom classloader...");         return defineClass(name, b,0, classSize);     }       public byte[] loadBinaryData(String name) throws ClassNotFoundException{         String pathName = name.replaceAll("\\.", "/");         File file = null;         for (String path : paths) {             file = new File(path+pathName+".class");             if(file.exists() && file.isFile()){                 break;             }         }         if(file==null || !file.isFile()){             throw  new ClassNotFoundException();         }         // 读取文件的二进制信息         try (InputStream in = new FileInputStream(file)){             // 一般这个大小够了,这里是为了方便读取             // 文件的内容,所以一次性读入,并且将大小返回             // 用于defineClass             byte[] b = new byte[1024 * 1024 * 10];             classSize = in.read(b);             return b;         }catch (IOException ioException){             ;         }         return null;     } }

这里加入了一个MyClassLoader自定义类加载器,扫描的路径为:

D:\\Users\\jeff.chan\\Desktop\\

那么新加入的类加载器就和app类加载器,扩展类加载器,启动类加载器一起起作用。

测试用例:

package reflect;     public class Person {       private String name;     private String age;       public Person() {     }       public Person(String name, String age) {         this.name = name;         this.age = age;     }       public String getName() {         return name;     }       public void setName(String name) {         this.name = name;     }       public String getAge() {         return age;     }       public void setAge(String age) {         this.age = age;     }       @Override     public String toString() {         return "Person{" +                 "name='" + name + '\'' +                 ", age='" + age + '\'' +                 '}';     } }

客户端:

package reflect;   public class Client {       public static void main(String[] args) throws Exception {         MyClassLoader classLoader = new MyClassLoader();         Class<?> aClass = classLoader.loadClass("reflect.Person");         System.out.println(aClass);         System.out.println(aClass.getClassLoader());     } }

时直接运行代码:那么会输出

发现自己的类加载器根本不起作用。其实是因为双亲委托机制:

1、MyClassLoader 查看是否已经加载 -》 2、App类加载查看是否已经加载 -》3、 扩展类加载器查看是否已经加载

-》 4、启动类加载器查看是否已经加载,没有加载就尝试加载 -》 5、扩展类尝试加载 -》 6、app类加载尝试加载 -》 7、MyClassLoader尝试加载 -》 8、抛出找不到类的异常

上述的流程中,第6步会找到对应的类,所以就直接返回了,根本没有给MyClassLoader机会加载,所以才没有调用自定义的类加载器MyClassLoader。

如果想要加载的话,那么就到编译生成的Person.class移动到桌面reflect/Person.class下,执行结果:

use custom classloader...class reflect.Personreflect.MyClassLoader@135fbaa4

结果发现,自定义的类加载起作用了,其实就是上述的流程中的第7步,找到了相应的类的二进制文件,加载了进来。

相关推荐:java入门

以上就是java实现自定义类加载器的详细内容,更多内容请关注技术你好其它相关文章!

来源链接:
免责声明:
1.资讯内容不构成投资建议,投资者应独立决策并自行承担风险
2.本文版权归属原作所有,仅代表作者本人观点,不代表本站的观点或立场
标签: 类加载器
上一篇:php获取远程图片并下载保存到本地的方法分析 下一篇:java实现导出excel文件

相关资讯