溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java虛擬機(jī)類裝載:原理、實(shí)現(xiàn)與應(yīng)用

發(fā)布時(shí)間:2020-08-17 14:00:14 來(lái)源:ITPUB博客 閱讀:152 作者:azz 欄目:編程語(yǔ)言
Java虛擬機(jī)類裝載:原理、實(shí)現(xiàn)與應(yīng)用[@more@]  一、引言

  Java虛擬機(jī)(JVM)的類裝載就是指將包含在類文件中的字節(jié)碼裝載到JVM中, 并使其成為JVM一部分的過(guò)程。JVM的類動(dòng)態(tài)裝載技術(shù)能夠在運(yùn)行時(shí)刻動(dòng)態(tài)地加載或者替換系統(tǒng)的某些功能模塊, 而不影響系統(tǒng)其他功能模塊的正常運(yùn)行。本文將分析JVM中的類裝載系統(tǒng),探討JVM中類裝載的原理、實(shí)現(xiàn)以及應(yīng)用。

  二、Java虛擬機(jī)的類裝載實(shí)現(xiàn)與應(yīng)用

  2.1 裝載過(guò)程簡(jiǎn)介

  所謂裝載就是尋找一個(gè)類或是一個(gè)接口的二進(jìn)制形式并用該二進(jìn)制形式來(lái)構(gòu)造代表這個(gè)類或是這個(gè)接口的class對(duì)象的過(guò)程,其中類或接口的名稱是給定了的。當(dāng)然名稱也可以通過(guò)計(jì)算得到,但是更常見(jiàn)的是通過(guò)搜索源代碼經(jīng)過(guò)編譯器編譯后所得到的二進(jìn)制形式來(lái)構(gòu)造。

  在Java中,類裝載器把一個(gè)類裝入Java虛擬機(jī)中,要經(jīng)過(guò)三個(gè)步驟來(lái)完成:裝載、鏈接和初始化,其中鏈接又可以分成校驗(yàn)、準(zhǔn)備和解析三步,除了解析外,其它步驟是嚴(yán)格按照順序完成的,各個(gè)步驟的主要工作如下:

  裝載:查找和導(dǎo)入類或接口的二進(jìn)制數(shù)據(jù);
  鏈接:執(zhí)行下面的校驗(yàn)、準(zhǔn)備和解析步驟,其中解析步驟是可以選擇的;
  校驗(yàn):檢查導(dǎo)入類或接口的二進(jìn)制數(shù)據(jù)的正確性;
  準(zhǔn)備:給類的靜態(tài)變量分配并初始化存儲(chǔ)空間;
  解析:將符號(hào)引用轉(zhuǎn)成直接引用;
  初始化:激活類的靜態(tài)變量的初始化Java代碼和靜態(tài)Java代碼塊。

  至于在類裝載和虛擬機(jī)啟動(dòng)的過(guò)程中的具體細(xì)節(jié)和可能會(huì)拋出的錯(cuò)誤,請(qǐng)參看《Java虛擬機(jī)規(guī)范》以及《深入Java虛擬機(jī)》,它們?cè)诰W(wǎng)絡(luò)上面的資源地址是:
  http://java.sun.com/docs/books/vmspec/2nd-edition/html/Preface.doc.html
  http://www.artima.com/insidejvm/ed2/index.html
  由于本文的討論重點(diǎn)不在此就不再多敘述。

  2.2 裝載的實(shí)現(xiàn)

  JVM中類的裝載是由ClassLoader和它的子類來(lái)實(shí)現(xiàn)的,Java ClassLoader 是一個(gè)重要的Java運(yùn)行時(shí)系統(tǒng)組件。它負(fù)責(zé)在運(yùn)行時(shí)查找和裝入類文件的類。

  在Java中,ClassLoader是一個(gè)抽象類,它在包java.lang中,可以這樣說(shuō),只要了解了在ClassLoader中的一些重要的方法,再結(jié)合上面所介紹的JVM中類裝載的具體的過(guò)程,對(duì)動(dòng)態(tài)裝載類這項(xiàng)技術(shù)就有了一個(gè)比較大概的掌握,這些重要的方法包括以下幾個(gè):

  ①loadCass方法 loadClass(String name ,boolean resolve)其中name參數(shù)指定了JVM需要的類的名稱,該名稱以包表示法表示,如Java.lang.Object;resolve參數(shù)告訴方法是否需要解析類,在初始化類之前,應(yīng)考慮類解析,并不是所有的類都需要解析,如果JVM只需要知道該類是否存在或找出該類的超類,那么就不需要解析。這個(gè)方法是ClassLoader 的入口點(diǎn)。

 ?、赿efineClass方法 這個(gè)方法接受類文件的字節(jié)數(shù)組并把它轉(zhuǎn)換成Class對(duì)象。字節(jié)數(shù)組可以是從本地文件系統(tǒng)或網(wǎng)絡(luò)裝入的數(shù)據(jù)。它把字節(jié)碼分析成運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)、校驗(yàn)有效性等等。

 ?、踗indSystemClass方法 findSystemClass方法從本地文件系統(tǒng)裝入文件。它在本地文件系統(tǒng)中尋找類文件,如果存在,就使用defineClass將字節(jié)數(shù)組轉(zhuǎn)換成Class對(duì)象,以將該文件轉(zhuǎn)換成類。當(dāng)運(yùn)行Java應(yīng)用程序時(shí),這是JVM 正常裝入類的缺省機(jī)制。

 ?、躵esolveClass方法 resolveClass(Class c)方法解析裝入的類,如果該類已經(jīng)被解析過(guò)那么將不做處理。當(dāng)調(diào)用loadClass方法時(shí),通過(guò)它的resolve 參數(shù)決定是否要進(jìn)行解析。

 ?、輋indLoadedClass方法 當(dāng)調(diào)用loadClass方法裝入類時(shí),調(diào)用findLoadedClass 方法來(lái)查看ClassLoader是否已裝入這個(gè)類,如果已裝入,那么返回Class對(duì)象,否則返回NULL。如果強(qiáng)行裝載已存在的類,將會(huì)拋出鏈接錯(cuò)誤。

  2.3 裝載的應(yīng)用

  一般來(lái)說(shuō),我們使用虛擬機(jī)的類裝載時(shí)需要繼承抽象類java.lang.ClassLoader,其中必須實(shí)現(xiàn)的方法是loadClass(),對(duì)于這個(gè)方法需要實(shí)現(xiàn)如下操作:(1) 確認(rèn)類的名稱;(2) 檢查請(qǐng)求要裝載的類是否已經(jīng)被裝載;(3) 檢查請(qǐng)求加載的類是否是系統(tǒng)類;(4) 嘗試從類裝載器的存儲(chǔ)區(qū)獲取所請(qǐng)求的類;(5) 在虛擬機(jī)中定義所請(qǐng)求的類;(6) 解析所請(qǐng)求的類;(7) 返回所請(qǐng)求的類。

  所有的Java 虛擬機(jī)都包括一個(gè)內(nèi)置的類裝載器,這個(gè)內(nèi)置的類庫(kù)裝載器被稱為根裝載器(bootstrap ClassLoader)。根裝載器的特殊之處是它只能夠裝載在設(shè)計(jì)時(shí)刻已知的類,因此虛擬機(jī)假定由根裝載器所裝載的類都是安全的、可信任的,可以不經(jīng)過(guò)安全認(rèn)證而直接運(yùn)行。當(dāng)應(yīng)用程序需要加載并不是設(shè)計(jì)時(shí)就知道的類時(shí),必須使用用戶自定義的裝載器(user-defined ClassLoader)。下面我們舉例說(shuō)明它的應(yīng)用。

  public abstract class MultiClassLoader extends ClassLoader{
  ...
  public synchronized Class loadClass(String s, boolean flag)
  throws ClassNotFoundException
  {
  /* 檢查類s是否已經(jīng)在本地內(nèi)存*/
  Class class1 = (Class)classes.get(s);

  /* 類s已經(jīng)在本地內(nèi)存*/
  if(class1 != null) return class1;
  try/*用默認(rèn)的ClassLoader 裝入類*/ {
  class1 = super.findSystemClass(s);
  return class1;
  }
  catch(ClassNotFoundException _ex) {
  System.out.println(">> Not a system class.");
  }

  /* 取得類s的字節(jié)數(shù)組*/
  byte abyte0[] = loadClassBytes(s);
  if(abyte0 == null) throw new ClassNotFoundException();

  /* 將類字節(jié)數(shù)組轉(zhuǎn)換為類*/
  class1 = defineClass(null, abyte0, 0, abyte0.length);
  if(class1 == null) throw new ClassFormatError();
  if(flag) resolveClass(class1); /*解析類*/

  /* 將新加載的類放入本地內(nèi)存*/
  classes.put(s, class1);
  System.out.println(">> Returning newly loaded class.");

  /* 返回已裝載、解析的類*/
  return class1;
  }
  ...
  }
向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI