Java類加載器

類加載器層次結構(由高到低)
1.引導類加載器 bootstrap class loader
做用:用來加載java的核心庫JAVA_HOME/jre/lib/rt.jar,不繼承自java.lang.ClassLoader
2.擴展類加載器 extensions class loader
做用:Java虛擬機的實現回提供一個擴展目錄,該類加載器在此目錄裏面查找並加載java類
3.應用程序類加載器 application class loader
做用:通常java應用類都是由它來完成
4.自定義類加載器
做用:實現本身的類加載器,以知足一些特殊要求
繼承java.lang.ClassLoader類
  自定義文件加載器:java

 1 import java.io.ByteArrayOutputStream;
 2 import java.io.FileInputStream;
 3 import java.io.FileNotFoundException;
 4 import java.io.IOException;
 5 import java.io.InputStream;
 6 
 7 /**
 8  * 自定義文件類加載器
 9  * 1.繼承java.lang.ClassLoader
10  * @author Nicotine
11  *
12  */
13 public class FileSystemClassLoader extends ClassLoader {
14     //com.sansan.test.User 在D:/test/讀取 
15     //文件路徑
16     private String rootDir;
17 
18     public FileSystemClassLoader(String rootDir) {
19         this.rootDir = rootDir;
20     }
21     @Override
22     protected Class<?> findClass(String name) throws ClassNotFoundException {
23     
24         Class<?> c = findLoadedClass(name);
25         
26         //先查看有沒有加載過這個類,若是已經加載過了,則直接返回;若是沒有,則加載新的類
27         if (null!=c) {
28             return c;
29         }else {
30             //雙親模式:獲取父類加載器,
31             ClassLoader parent = this.getParent();
32             try {
33                 c = parent.getClass();
34             } catch (Exception e) {
35             }
36         }
37         if (null!=c) {
38             return c;
39         }else {
40             byte[] classData = getClassData(name);
41             if (null==classData) {
42                 throw new ClassNotFoundException();
43             }else{
44                 c=defineClass(name, classData, 0,classData.length);
45             }
46         }
47         return c;
48     }
49     private byte[] getClassData(String classname) {
50         //源數據路徑
51         String path = rootDir + "/"+classname.replace(".","/")+".class";
52         //讀取
53         //IOUtils,能夠使用它將IO流的數據轉換成字節數組
54         //選擇流
55         InputStream is = null;
56         ByteArrayOutputStream baos = new ByteArrayOutputStream();
57         
58         try {
59             is=new  FileInputStream(path);
60             byte[] buffer = new byte[1024];
61             int temp = 0;
62             //讀取
63             while ((temp=is.read(buffer))!= -1) {
64                 baos.write(buffer,0,temp);
65             }
66             return baos.toByteArray();
67         } catch (FileNotFoundException e) {
68             e.printStackTrace();
69             return null;
70         } catch (IOException e) {
71             e.printStackTrace();
72             return null;
73         }finally{
74             if (is!=null) {
75                 try {
76                     is.close();
77                 } catch (IOException e) {
78                     e.printStackTrace();
79                 }
80             }
81             if (baos!=null) {
82                 try {
83                     baos.close();
84                 } catch (IOException e) {
85                     e.printStackTrace();
86                 }
87             }
88         }
89     }
90 }

測試代碼:bootstrap

public class TestFileClass {
    public static void main(String[] args) throws ClassNotFoundException {
        FileSystemClassLoader loader = new FileSystemClassLoader("D:/test");
        Class<?> c = loader.loadClass("com.sansan.test.HelloWorld");
        System.out.println(c.hashCode());
    }
}

運行輸出類的哈希值數組


java.lang.ClassLoader類
根據一個指定的類的名稱,找到或者生成其對應的字節碼,而後從這些字節碼中定義一個java類,級java.lang.Class的一個實例
相關方法
getParent() 返回該類加載器的父類加載器
loadClass(String name) 加載名稱爲name的類,返回結果就是java.lang.Class類的實例
findClass(String name) 查找名稱爲name的類,返回結果就是java.lang.Class類的實例
findLoadedClass(String name) 查找名稱爲name的已經被加載過的類,返回結果就是java.lang.Class類的實例
defineClass(String name,byte[] b,int off,int len)把字節數組b中的內容轉換成java類,返回結果就是java.lang.Class類的實例
resolveClass(Class<?> c)連接指定的Java類


通常採用代理模式
交給其它加載器來加載指定的類
雙親委託機制
父類加載器優先加載
爲了保證java核心庫的類型安全
這種機制就保證不會出現用戶本身能定義java.lang.Object類的狀況
雙親委託機制是代理模式的一種
並非全部的類加載器都採用雙親委託機制
Tomcat服務器加載器也是用代理模式,所不一樣的是它首先嚐試去加載某各種,若是找不到在代理給父類加載器,這與通常的加載器順序相反


安全

相關文章
相關標籤/搜索