第九篇 JVM核心机制之JVM运行和类加载全过程(四)

(1)从上面源码看出,调用loadClass时会先根据委派模型在父加载器中加载,如果加载失败,则会调用当前加载器的findClass来完成加载。

(2)因此我们自定义的类加载器只需要继承ClassLoader,并覆盖findClass方法,下面是一个实际例子,在该例中我们用自定义的类加载器去加载我们事先准备好的class文件。

  

 1 /**
 2  * 自定义文件系统类加载器
 3  *
 4  * @author Zhang XiaoDao
 5  *
 6  */
 7 public class FileSystemClassLoader extends ClassLoader{
 8     
 9     private String rootDir;
10 
11     public FileSystemClassLoader(String rootDir) {
12         super();
13         this.rootDir = rootDir;
14     }
15     
16     @Override
17     protected Class<?> findClass(String name) throws ClassNotFoundException {
18         Class<?> c = findLoadedClass(name);
19         //应该要先查询有没有加载过这个类,如果已经加载,则直接返回这个类。如果没有加载,则返回新的类
20         if(c != null){
21             return c;
22         }else{
23             ClassLoader parent = this.getParent();
24             c = parent.loadClass(name);
25             if(c != null){
26                 return c;
27             }else{
28                 byte[] classData = getClassData(name);
29                 if(classData == null){
30                     throw new ClassNotFoundException();
31                 }else{
32                     c = defineClass(name, classData, 0, classData.length);
33                 }
34             }
35         }
36         return c;
37     }
38     
39     private byte[] getClassData(String classname){//com.bjsxt.test.User  --> d:/java/ com/bjsxt/test/User.class
40         String path = rootDir + "/" + classname.replace('.', '/') + ".class";
41         //IOUtils 可以使用它将流中的数据转成字节数组
42         InputStream is = null;
43         ByteArrayOutputStream  baOutputStream = new ByteArrayOutputStream();
44         try {
45             is = new FileInputStream(path);
46             byte[] buffer = new byte[1024];
47             int temp = 0;
48             while((temp= is.read(buffer))!=-1){
49                 baOutputStream.write(buffer, 0, temp);
50             }
51             return baOutputStream.toByteArray();
52         } catch (Exception e) {
53             e.printStackTrace();
54             return null;
55         }finally {
56             if(is != null){
57                 try {
58                     is.close();
59                 } catch (IOException e) {
60                     e.printStackTrace();
61                 }
62             }
63             if(baOutputStream != null){
64                 try {
65                     baOutputStream.close();
66                 } catch (IOException e) {
67                     e.printStackTrace();
68                 }
69             }
70         }        
71 //        return null;        
72     }
73     
74 }

 

 1 /**
 2  * 
 3  * 测试自定义加载器
 4  *
 5  * @author Zhang XiaoDao
 6  *
 7  */
 8 public class Demo03 {
 9     public static void main(String[] args) throws ClassNotFoundException {
10         FileSystemClassLoader loader = new FileSystemClassLoader("d:/java");
11         FileSystemClassLoader loader2 = new FileSystemClassLoader("d:/java");
12         
13         Class<?> c1 = loader.loadClass("com.zzp.user");
14         Class<?> c2 = loader.loadClass("com.zzp.user");
15         //同一个类被不同的加载器加载,jvm会认为是不同的类
16         Class<?> c3 = loader2.loadClass("com.zzp.user");
17         Class<?> c4 = loader2.loadClass("java.lang.String");
18         Class<?> c5 = loader2.loadClass("com.Demo01");
19         
20         
21         System.out.println(c1);
22         System.out.println(c2);
23         System.out.println(c3.getClassLoader());//自定义类加载器
24         System.out.println(c4.getClassLoader());//引导类加载器
25         System.out.println(c5.getClassLoader());//系统类加载器
26     }
27 }

网络类加载器:

 1 /**
 2  * 网络类加载器
 3  *
 4  * @author Zhang XiaoDao
 5  *
 6  */
 7 public class NetClassLoader extends ClassLoader{
 8     
 9     private String rootUrl;
10 
11     public NetClassLoader(String rootUrl) {
12         super();
13         this.rootUrl = rootUrl;
14     }
15     
16     @Override
17     protected Class<?> findClass(String name) throws ClassNotFoundException {
18         Class<?> c = findLoadedClass(name);
19         //应该要先查询有没有加载过这个类,如果已经加载,则直接返回这个类。如果没有加载,则返回新的类
20         if(c != null){
21             return c;
22         }else{
23             ClassLoader parent = this.getParent();
24             c = parent.loadClass(name);
25             if(c != null){
26                 return c;
27             }else{
28                 byte[] classData = getClassData(name);
29                 if(classData == null){
30                     throw new ClassNotFoundException();
31                 }else{
32                     c = defineClass(name, classData, 0, classData.length);
33                 }
34             }
35         }
36         return c;
37     }
38     
39     private byte[] getClassData(String classname){//com.bjsxt.test.User  --> d:/java/ com/bjsxt/test/User.class
40         String path = rootUrl + "/" + classname.replace('.', '/') + ".class";
41         //IOUtils 可以使用它将流中的数据转成字节数组
42         InputStream is = null;
43         ByteArrayOutputStream  baOutputStream = new ByteArrayOutputStream();
44         try {
45             URL url = new URL(path);
46             is = url.openStream();
47             byte[] buffer = new byte[1024];
48             int temp = 0;
49             while((temp= is.read(buffer))!=-1){
50                 baOutputStream.write(buffer, 0, temp);
51             }
52             return baOutputStream.toByteArray();
53         } catch (Exception e) {
54             e.printStackTrace();
55             return null;
56         }finally {
57             if(is != null){
58                 try {
59                     is.close();
60                 } catch (IOException e) {
61                     e.printStackTrace();
62                 }
63             }
64             if(baOutputStream != null){
65                 try {
66                     baOutputStream.close();
67                 } catch (IOException e) {
68                     e.printStackTrace();
69                 }
70             }
71         }        
72 //        return null;        
73     }
74     
75 }

 

posted on 2018-06-05 00:04  奋斗的小刀001  阅读(150)  评论(0编辑  收藏  举报

导航