国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術(shù)|正則表達(dá)式|

服務(wù)器之家 - 編程語言 - JAVA教程 - Java 類加載機(jī)制詳細(xì)介紹

Java 類加載機(jī)制詳細(xì)介紹

2020-09-28 13:23Java教程網(wǎng) JAVA教程

這篇文章主要介紹了Java 類加載機(jī)制詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下

一、類加載器

  類加載器(classloader),顧名思義,即加載類的東西。在我們使用一個(gè)類之前,jvm需要先將該類的字節(jié)碼文件(.class文件)從磁盤、網(wǎng)絡(luò)或其他來源加載到內(nèi)存中,并對(duì)字節(jié)碼進(jìn)行解析生成對(duì)應(yīng)的class對(duì)象,這就是類加載器的功能。我們可以利用類加載器,實(shí)現(xiàn)類的動(dòng)態(tài)加載。

二、類的加載機(jī)制

  在java中,采用雙親委派機(jī)制來實(shí)現(xiàn)類的加載。那什么是雙親委派機(jī)制?在java doc中有這樣一段描述:

?
1
2
3
4
5
6
the classloader class uses a delegation model to search for classes and resources. each instance
 of classloader has an associated parent class loader. when requested to find a class or resource,
 a classloader instance will delegate the search for the class or resource to its parent class loader
 before attempting to find the class or resource itself. the virtual machine's built-in class loader,
 called the "bootstrap class loader", does not itself have a parent but may serve as the parent of a
 classloader instance.

 從以上描述中,我們可以總結(jié)出如下四點(diǎn):

1、類的加載過程采用委托模式實(shí)現(xiàn)

2、每個(gè) classloader 都有一個(gè)父加載器。

3、類加載器在加載類之前會(huì)先遞歸的去嘗試使用父加載器加載。

4、虛擬機(jī)有一個(gè)內(nèi)建的啟動(dòng)類加載器(bootstrap classloader),該加載器沒有父加載器,但是可以作為其他加載器的父加載器。

   java 提供三種類型的系統(tǒng)類加載器。第一種是啟動(dòng)類加載器,由c++語言實(shí)現(xiàn),屬于jvm的一部分,其作用是加載 <java_runtime_home>/lib 目錄中的文件,并且該類加載器只加載特定名稱的文件(如 rt.jar),而不是該目錄下所有的文件。另外兩種是 java 語言自身實(shí)現(xiàn)的類加載器,包括擴(kuò)展類加載器(extclassloader)和應(yīng)用類加載器(appclassloader),擴(kuò)展類加載器負(fù)責(zé)加載<java_runtime_home>\lib\ext目錄中或系統(tǒng)變量 java.ext.dirs 所指定的目錄中的文件。應(yīng)用程序類加載器負(fù)責(zé)加載用戶類路徑中的文件。用戶可以直接使用擴(kuò)展類加載器或系統(tǒng)類加載器來加載自己的類,但是用戶無法直接使用啟動(dòng)類加載器,除了這兩種類加載器以外,用戶也可以自定義類加載器,加載流程如下圖所示:

Java 類加載機(jī)制詳細(xì)介紹

  注意:這里父類加載器并不是通過繼承關(guān)系來實(shí)現(xiàn)的,而是采用組合實(shí)現(xiàn)的。

  我們可以通過一段程序來驗(yàn)證這個(gè)過程:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class test {
}
 
public class testmain {
  public static void main(string[] args) {
 
    classloader loader = test.class.getclassloader();
    while (loader!=null){
      system.out.println(loader);
      loader = loader.getparent();
    }
  }
}

  上面程序的運(yùn)行結(jié)果如下所示:  

Java 類加載機(jī)制詳細(xì)介紹

  從結(jié)果我們可以看出,默認(rèn)情況下,用戶自定義的類使用 appclassloader 加載,appclassloader 的父加載器為 extclassloader,但是 extclassloader 的父加載器卻顯示為空,這是什么原因呢?究其緣由,啟動(dòng)類加載器屬于 jvm 的一部分,它不是由 java 語言實(shí)現(xiàn)的,在 java 中無法直接引用,所以才返回空。但如果是這樣,該怎么實(shí)現(xiàn) extclassloader 與 啟動(dòng)類加載器之間雙親委派機(jī)制?我們可以參考一下源碼:

?
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
protected class<?> loadclass(string name, boolean resolve)
    throws classnotfoundexception
  {
    synchronized (getclassloadinglock(name)) {
      // first, check if the class has already been loaded
      class<?> c = findloadedclass(name);
      if (c == null) {
        long t0 = system.nanotime();
        try {
          if (parent != null) {
            c = parent.loadclass(name, false);
          } else {
            c = findbootstrapclassornull(name);
          }
        } catch (classnotfoundexception e) {
          // classnotfoundexception thrown if class not found
          // from the non-null parent class loader
        }
 
        if (c == null) {
          // if still not found, then invoke findclass in order
          // to find the class.
          long t1 = system.nanotime();
          c = findclass(name);
 
          // this is the defining class loader; record the stats
          sun.misc.perfcounter.getparentdelegationtime().addtime(t1 - t0);
          sun.misc.perfcounter.getfindclasstime().addelapsedtimefrom(t1);
          sun.misc.perfcounter.getfindclasses().increment();
        }
      }
      if (resolve) {
        resolveclass(c);
      }
      return c;
    }
  }

  從源碼可以看出,extclassloader 和 appclassloader都繼承自 classloader 類,classloader 類中通過 loadclass 方法來實(shí)現(xiàn)雙親委派機(jī)制。整個(gè)類的加載過程可分為如下三步:

  1、查找對(duì)應(yīng)的類是否已經(jīng)加載。

  2、若未加載,則判斷當(dāng)前類加載器的父加載器是否為空,不為空則委托給父類去加載,否則調(diào)用啟動(dòng)類加載器加載(findbootstrapclassornull 再往下會(huì)調(diào)用一個(gè) native 方法)。

  3、若第二步加載失敗,則調(diào)用當(dāng)前類加載器加載。

  通過上面這段程序,可以很清楚的看出擴(kuò)展類加載器與啟動(dòng)類加載器之間是如何實(shí)現(xiàn)委托模式的。

      現(xiàn)在,我們?cè)衮?yàn)證另一個(gè)問題。我們將剛才的test類打成jar包,將其放置在 <java_runtime_home>\lib\ext 目錄下,然后再次運(yùn)行上面的代碼,結(jié)果如下:

Java 類加載機(jī)制詳細(xì)介紹

     現(xiàn)在,該類就不再通過 appclassloader 來加載,而是通過 extclassloader 來加載了。如果我們?cè)噲D把jar包拷貝到<java_runtime_home>\lib,嘗試通過啟動(dòng)類加載器加載該類時(shí),我們會(huì)發(fā)現(xiàn)編譯器無法識(shí)別該類,因?yàn)閱?dòng)類加載器除了指定目錄外,還必須是特定名稱的文件才能加載。

三、自定義類加載器

  通常情況下,我們都是直接使用系統(tǒng)類加載器。但是,有的時(shí)候,我們也需要自定義類加載器。比如應(yīng)用是通過網(wǎng)絡(luò)來傳輸 java 類的字節(jié)碼,為保證安全性,這些字節(jié)碼經(jīng)過了加密處理,這時(shí)系統(tǒng)類加載器就無法對(duì)其進(jìn)行加載,這樣則需要自定義類加載器來實(shí)現(xiàn)。自定義類加載器一般都是繼承自 classloader 類,從上面對(duì) loadclass 方法來分析來看,我們只需要重寫 findclass 方法即可。下面我們通過一個(gè)示例來演示自定義類加載器的流程:

?
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
58
59
60
61
62
63
64
65
66
67
package com.paddx.test.classloading;
 
import java.io.*;
 
/**
 * created by liuxp on 16/3/12.
 */
public class myclassloader extends classloader {
 
  private string root;
 
  protected class<?> findclass(string name) throws classnotfoundexception {
    byte[] classdata = loadclassdata(name);
    if (classdata == null) {
      throw new classnotfoundexception();
    } else {
      return defineclass(name, classdata, 0, classdata.length);
    }
  }
 
  private byte[] loadclassdata(string classname) {
    string filename = root + file.separatorchar
        + classname.replace('.', file.separatorchar) + ".class";
    try {
      inputstream ins = new fileinputstream(filename);
      bytearrayoutputstream baos = new bytearrayoutputstream();
      int buffersize = 1024;
      byte[] buffer = new byte[buffersize];
      int length = 0;
      while ((length = ins.read(buffer)) != -1) {
        baos.write(buffer, 0, length);
      }
      return baos.tobytearray();
    } catch (ioexception e) {
      e.printstacktrace();
    }
    return null;
  }
 
  public string getroot() {
    return root;
  }
 
  public void setroot(string root) {
    this.root = root;
  }
 
  public static void main(string[] args) {
 
    myclassloader classloader = new myclassloader();
    classloader.setroot("/users/liuxp/tmp");
 
    class<?> testclass = null;
    try {
      testclass = classloader.loadclass("com.paddx.test.classloading.test");
      object object = testclass.newinstance();
      system.out.println(object.getclass().getclassloader());
    } catch (classnotfoundexception e) {
      e.printstacktrace();
    } catch (instantiationexception e) {
      e.printstacktrace();
    } catch (illegalaccessexception e) {
      e.printstacktrace();
    }
  }
}

  運(yùn)行上面的程序,輸出結(jié)果如下:

  Java 類加載機(jī)制詳細(xì)介紹

  自定義類加載器的核心在于對(duì)字節(jié)碼文件的獲取,如果是加密的字節(jié)碼則需要在該類中對(duì)文件進(jìn)行解密。由于這里只是演示,我并未對(duì)class文件進(jìn)行加密,因此沒有解密的過程。這里有幾點(diǎn)需要注意:

  1、這里傳遞的文件名需要是類的全限定性名稱,即com.paddx.test.classloading.test格式的,因?yàn)?defineclass 方法是按這種格式進(jìn)行處理的。

  2、最好不要重寫loadclass方法,因?yàn)檫@樣容易破壞雙親委托模式。

  3、這類 test 類本身可以被 appclassloader 類加載,因此我們不能把 com/paddx/test/classloading/test.class 放在類路徑下。否則,由于雙親委托機(jī)制的存在,會(huì)直接導(dǎo)致該類由 appclassloader 加載,而不會(huì)通過我們自定義類加載器來加載。

  四、總結(jié)

  雙親委派機(jī)制能很好地解決類加載的統(tǒng)一性問題。對(duì)一個(gè) class 對(duì)象來說,如果類加載器不同,即便是同一個(gè)字節(jié)碼文件,生成的 class 對(duì)象也是不等的。也就是說,類加載器相當(dāng)于 class 對(duì)象的一個(gè)命名空間。雙親委派機(jī)制則保證了基類都由相同的類加載器加載,這樣就避免了同一個(gè)字節(jié)碼文件被多次加載生成不同的 class 對(duì)象的問題。但雙親委派機(jī)制僅僅是java 規(guī)范所推薦的一種實(shí)現(xiàn)方式,它并不是強(qiáng)制性的要求。近年來,很多熱部署的技術(shù)都已不遵循這一規(guī)則,如 osgi 技術(shù)就采用了一種網(wǎng)狀的結(jié)構(gòu),而非雙親委派機(jī)制。

感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久久久久免费毛片精品 | 日韩综合网 | 久久久高清 | 一级黄色大片 | 天堂av中文字幕 | 激情中文网| 亚洲综合在线视频 | 色片在线观看 | 欧美一区二区三区精品 | 欧美大片免费影院在线观看 | 天天精品视频免费观看 | 91在线电影 | 天天操天天干天天爽 | 青青草免费在线视频 | 国产精品色一区二区三区 | 久久精品小视频 | 欧美日韩亚洲系列 | 黄色裸体网站 | 久久综合一区二区三区 | 久久精品久久久 | 黄在线看| 日本中文字幕网 | 农村末发育av片四区五区 | 免费观看av | 在线亚洲电影 | 深夜网址| 欧美三级电影在线播放 | 久久国产精品久久国产精品 | 亚洲 欧美 日韩 在线 | 91.成人天堂一区 | 一特黄a大片免费视频 视频 | 日韩亚洲在线 | a级在线观看| 久久人人爽爽爽人久久久 | 色爽 | 九九九久久久 | 成视频年人免费看黄网站 | 亚洲美女二区 | 国产精品一区二 | 最近2018年手机中文字幕版 | 欧美xo影院|