自定義ClassLoader

第一節咱們說過一句話:全部的Java虛擬機實現必須在每一個類或接口被Java程序「 首次主動使用」時才初始化他們java

但類加載器卻不是這樣:類加載器不須要等到某個類「被首次主動使用」時才加載數組

兩句話的區別就在於紅線標註的地方,因此咱們要明確一點ClassLoader只負責類的加載,即 加載  》 鏈接 》初始化 的第一步安全

由上一節咱們知道,jvm有三種加載器,每種加載器負責特定目錄的類。根類加載器(BootStrap)和擴展加載器(Extension)沒必要說,它們負責加載的都是特定目錄的類,並且這些類是固定的,咱們不能說咱們把本身編寫的類加到java.lang目錄下就能使這個類被根類加載器加載,那樣就太不安全了。由於加載的類是固定的就很好理解,可是系統類加載器(System)就比較很差理解了,它是加載classpath定義的目錄下的類。並且咱們知道classpath路徑是能夠自定義的,也就是說它能夠加載任意目錄的類,只要咱們在classpath下指定了該目錄。jvm

好比咱們安裝好jdk配置好環境變量以後,咱們就能夠在任意位置使用javac命令和java命令,可是你有沒有想過,咱們並無指定類加載的路徑,爲何咱們在任何地方都能加載到目標類文件呢。緣由很簡單就是環境變量的配置,咱們通常回配置兩個參數path和classpath。path的做用是讓咱們在任意目錄下都能找到javac和java命令,可是單單找到命令是不夠的,有命令沒有類文件同樣白搭,因此classpath的設置就是幫咱們找到類文件,classpath通常這樣設置     .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar  。注意最開始的那個點,最不起眼卻最重要,它表明當前文件夾,當咱們在一個很偏僻的文件夾使用javac命令編譯java文件,這個文件夾就是咱們工做的當前文件夾,jvm就會到path下去尋找javac命令,path配置正確找到命令。而後到classpath下去尋找class文件,而後就發現了  "  .  " ,因而就會到當前文件夾下尋找,一下就找到了,類編譯就完成了,java命令同樣。this

如今系統類加載器(System)已經很清楚了。那咱們能不能本身編寫本身的類加載器呢,答案是確定的,固然,類加載很複雜,要咱們從零作起是不現實的,咱們只能根據已有的類加載器進行包裝,定製本身的ClassLoaderspa

自定義類加載器分爲如下幾個步驟:code

一、定義類。繼承ClassLoader繼承

二、重寫ClassLoader的 findClass方法接口

就是這麼簡單,下面是我本身寫的自定義類加載器例子ci

 

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

public class MyClassLoader extends ClassLoader{

 

    private String path;   //類的加載路徑

    private String name;   //類加載器的名字

 

    public MyClassLoader() {}

    public MyClassLoader(String path,String name){

        this.path = path;

        this.name = name;

    }

 

 

    //用於尋找類文件

    public Class findClass(String name) {

        byte[] b = loadClassData(name);

        return defineClass(name, b, 0, b.length);

    }

 

    //用於加載類文件

    private byte[] loadClassData(String name) {

 

        name = path + name + ".class";    

        //使用輸入流讀取類文件

        InputStream in = null;

        //使用byteArrayOutputStream保存類文件。而後轉化爲byte數組

        ByteArrayOutputStream out = null;

        try {

            in = new FileInputStream(new File(name));

            out = new ByteArrayOutputStream();

            int i = 0;

            while ( (i = in.read()) != -1){

                out.write(i);

            }

 

        }catch (Exception e){}

        finally {

            try {

                out.close();

                in.close();

            } catch (IOException e) {

                e.printStackTrace();

            }

 

        }

 

        return out.toByteArray();

 

    }

 

    public String getName() {

        return name;

    }

 

    public void setPath(String path) {

        this.path = path;

    }

}

  而後調用

 

1

2

3

4

5

6

7

public static void main(String[] args) {

        MyClassLoader m = new MyClassLoader("/home/fanjie/code/","classLoad1");

 

        Class c = m.findClass("Hello");

        System.out.println(c.getClassLoader());

 

    }

  結果 : classLoader.MyClassLoader@60e53b93

相關文章
相關標籤/搜索