Java 理解类加载过程 -- 自定义加载器

Posted 行者老夫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 理解类加载过程 -- 自定义加载器相关的知识,希望对你有一定的参考价值。

类加载器可以看下我的收藏:

  https://www.cnblogs.com/dongguacai/p/5879931.html

现在准备一个字节码文件:

 

 

自定义加载器:

 1 package com.xzlf.test;
 2 
 3 import java.io.ByteArrayOutputStream;
 4 import java.io.FileInputStream;
 5 import java.io.IOException;
 6 import java.io.InputStream;
 7 
 8 /**
 9  * 自定义类加载器
10  * 
11  * @author xzlf
12  *
13  */
14 public class MyClassLoader extends ClassLoader {
15     // 类加载器查找的根目录
16     private String rootDir;
17 
18     public MyClassLoader(String rootDir) {
19         super();
20         this.rootDir = rootDir;
21     }
22 
23     @Override
24     protected Class<?> findClass(String name) throws ClassNotFoundException {
25         // 查看 c 是否已经被加载
26         Class<?> c = findLoadedClass(name);
27         if(c != null) {
28             // 已经加载直接返回
29             return c;
30         }else {
31             // 没有被加载,先委派给父类加载器, 最终会委派到引导类加载器
32             ClassLoader parent = this.getParent();
33             try {
34                 c = parent.loadClass(name);
35             } catch (ClassNotFoundException e) {
36                 //e.printStackTrace();
37             }
38             // 如果父类加载器已加载则直接返回,如果没有加载则使用自定加载器加载类的字节码文件
39             if(c != null) {
40                 return c;
41             }else {
42                 // 获取字节码文件
43                 byte[] classDatas = getClassData(name);
44                 if(classDatas == null) {
45                     throw new ClassNotFoundException();
46                 }else {
47                     //Converts an array of bytes into an instance of class
48                     c = defineClass(name, classDatas, 0, classDatas.length);
49                 }
50             }
51         }
52         return c;
53     }
54 
55     // 获取字节码文件
56     private byte[] getClassData(String name) {
57         //com.test.A --> f:/mycode/  com/test/A.class
58         String path = rootDir + "/" + name.replace(\'.\', \'/\') + ".class";
59         
60         // IO 操作 返回字节码
61         InputStream is = null;
62         ByteArrayOutputStream bos = new ByteArrayOutputStream();
63         try {
64             is = new FileInputStream(path);
65             byte[] flush = new byte[1024];
66             int len;
67             while((len = is.read(flush)) != -1) {
68                 bos.write(flush, 0, len);
69             }
70             return bos.toByteArray();
71         } catch (Exception e) {
72             e.printStackTrace();
73         }finally {
74             if(bos != null) {
75                 try {
76                     bos.close();
77                 } catch (IOException e) {
78                     e.printStackTrace();
79                 }
80             }
81             if(is != null) {
82                 try {
83                     is.close();
84                 } catch (IOException e) {
85                     e.printStackTrace();
86                 }
87             }
88         }
89         return null;
90     }
91 }

测试代码:

 

 1 package com.xzlf.test;
 2 
 3 public class TestClassLoader {
 4     public static void main(String[] args) throws Exception {
 5         MyClassLoader loader1 = new MyClassLoader("f:/mycode");
 6         MyClassLoader loader2 = new MyClassLoader("f:/mycode");
 7         
 8         Class<?> c1 = loader1.loadClass("com.test.Welcome");
 9         Class<?> c2 = loader1.loadClass("com.test.Welcome");
10         Class<?> c3 = loader2.loadClass("com.test.Welcome");
11         
12         Class<?> c4 = loader2.loadClass("java.lang.String");
13         Class<?> c5 = loader2.loadClass("com.xzlf.test.MyClassLoader");
14         
15         // 自定义加载器
16         System.out.println("c1-->" + c1.hashCode() + "-->" + c1.getClassLoader());
17         System.out.println("c2-->" + c2.hashCode() + "-->" + c2.getClassLoader());
18         
19         // 同一个类,被不同的加载器加载,JVM认为也是不相同的类
20         System.out.println("c3-->" + c3.hashCode() + "-->" + c3.getClassLoader());
21         
22         // 引导加载器
23         System.out.println("c4-->" + c4.hashCode() + "-->" + c4.getClassLoader());
24         
25         // 应用加载器
26         System.out.println("c5-->" + c5.hashCode() + "-->" + c5.getClassLoader());
27     }
28 }

运行测试:

 

 

以上是关于Java 理解类加载过程 -- 自定义加载器的主要内容,如果未能解决你的问题,请参考以下文章

深入理解Java虚拟机——类加载器

Java中类加载器的分析与理解!详细解析类的加载过程

面试干货4——你对Java类加载器(自定义类加载器)有了解吗?

java 自定义类的加载器

面试必看-Java类加载器(自定义类加载器)

Java 类加载器(转载)