欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Java虛擬機類(lèi)裝載:原理、實(shí)現與應用 - bon
Java虛擬機類(lèi)裝載:原理、實(shí)現與應用

Java虛擬機類(lèi)裝載:原理、實(shí)現與應用

作者:劉學(xué)超

一、引言

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

二、Java虛擬機的類(lèi)裝載實(shí)現與應用

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

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

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

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

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

2.2  裝載的實(shí)現

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

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

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

②defineClass方法  這個(gè)方法接受類(lèi)文件的字節數組并把它轉換成Class對象。字節數組可以是從本地文件系統或網(wǎng)絡(luò )裝入的數據。它把字節碼分析成運行時(shí)數據結構、校驗有效性等等。

③findSystemClass方法  findSystemClass方法從本地文件系統裝入文件。它在本地文件系統中尋找類(lèi)文件,如果存在,就使用defineClass將字節數組轉換成Class對象,以將該文件轉換成類(lèi)。當運行Java應用程序時(shí),這是JVM 正常裝入類(lèi)的缺省機制。

④resolveClass方法  resolveClass(Class c)方法解析裝入的類(lèi),如果該類(lèi)已經(jīng)被解析過(guò)那么將不做處理。當調用loadClass方法時(shí),通過(guò)它的resolve 參數決定是否要進(jìn)行解析。

⑤findLoadedClass方法  當調用loadClass方法裝入類(lèi)時(shí),調用findLoadedClass 方法來(lái)查看ClassLoader是否已裝入這個(gè)類(lèi),如果已裝入,那么返回Class對象,否則返回NULL。如果強行裝載已存在的類(lèi),將會(huì )拋出鏈接錯誤。

2.3  裝載的應用

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

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

public abstract class MultiClassLoader extends ClassLoader{    ...    public synchronized Class loadClass(String s, boolean flag)        throws ClassNotFoundException    {        /* 檢查類(lèi)s是否已經(jīng)在本地內存*/        Class class1 = (Class)classes.get(s);        /* 類(lèi)s已經(jīng)在本地內存*/        if(class1 != null)  return class1;         try/*用默認的ClassLoader 裝入類(lèi)*/  {            class1 = super.findSystemClass(s);            return class1;        }        catch(ClassNotFoundException _ex)  {            System.out.println(">> Not a system class.");        }        /* 取得類(lèi)s的字節數組*/        byte abyte0[] = loadClassBytes(s);        if(abyte0 == null)   throw new ClassNotFoundException();        /* 將類(lèi)字節數組轉換為類(lèi)*/        class1 = defineClass(null, abyte0, 0, abyte0.length);        if(class1 == null) throw new ClassFormatError();        if(flag)   resolveClass(class1); /*解析類(lèi)*/        /* 將新加載的類(lèi)放入本地內存*/        classes.put(s, class1);        System.out.println(">> Returning newly loaded class.");        /* 返回已裝載、解析的類(lèi)*/        return class1;    }    ...}

三、Java虛擬機的類(lèi)裝載原理

前面我們已經(jīng)知道,一個(gè)Java應用程序使用兩種類(lèi)型的類(lèi)裝載器:根裝載器(bootstrap)和用戶(hù)定義的裝載器(user-defined)。根裝載器是Java虛擬機實(shí)現的一部分,舉個(gè)例子來(lái)說(shuō),如果一個(gè)Java虛擬機是在現在已經(jīng)存在并且正在被使用的操作系統的頂部用C程序來(lái)實(shí)現的,那么根裝載器將是那些C程序的一部分。根裝載器以某種默認的方式將類(lèi)裝入,包括那些Java API的類(lèi)。在運行期間一個(gè)Java程序能安裝用戶(hù)自己定義的類(lèi)裝載器。根裝載器是虛擬機固有的一部分,而用戶(hù)定義的類(lèi)裝載器則不是,它是用Java語(yǔ)言寫(xiě)的,被編譯成class文件之后然后再被裝入到虛擬機,并像其它的任何對象一樣可以被實(shí)例化。 Java類(lèi)裝載器的體系結構如下所示:

圖1  Java的類(lèi)裝載的體系結構

Java的類(lèi)裝載模型是一種代理(delegation)模型。當JVM 要求類(lèi)裝載器CL(ClassLoader)裝載一個(gè)類(lèi)時(shí),CL首先將這個(gè)類(lèi)裝載請求轉發(fā)給他的父裝載器。只有當父裝載器沒(méi)有裝載并無(wú)法裝載這個(gè)類(lèi)時(shí),CL才獲得裝載這個(gè)類(lèi)的機會(huì )。這樣, 所有類(lèi)裝載器的代理關(guān)系構成了一種樹(shù)狀的關(guān)系。樹(shù)的根是類(lèi)的根裝載器(bootstrap ClassLoader) , 在JVM 中它以"null"表示。除根裝載器以外的類(lèi)裝載器有且僅有一個(gè)父裝載器。在創(chuàng )建一個(gè)裝載器時(shí), 如果沒(méi)有顯式地給出父裝載器, 那么JVM將默認系統裝載器為其父裝載器。Java的基本類(lèi)裝載器代理結構如圖2所示:

圖2  Java類(lèi)裝載的代理結構

下面針對各種類(lèi)裝載器分別進(jìn)行詳細的說(shuō)明。

根(Bootstrap) 裝載器:該裝載器沒(méi)有父裝載器,它是JVM實(shí)現的一部分,從sun.boot.class.path裝載運行時(shí)庫的核心代碼。

擴展(Extension) 裝載器:繼承的父裝載器為根裝載器,不像根裝載器可能與運行時(shí)的操作系統有關(guān),這個(gè)類(lèi)裝載器是用純Java代碼實(shí)現的,它從java.ext.dirs (擴展目錄)中裝載代碼。

系統(System or Application) 裝載器:裝載器為擴展裝載器,我們都知道在安裝JDK的時(shí)候要設置環(huán)境變量(CLASSPATH ),這個(gè)類(lèi)裝載器就是從java.class.path(CLASSPATH 環(huán)境變量)中裝載代碼的,它也是用純Java代碼實(shí)現的,同時(shí)還是用戶(hù)自定義類(lèi)裝載器的缺省父裝載器。

小應用程序(Applet) 裝載器: 裝載器為系統裝載器,它從用戶(hù)指定的網(wǎng)絡(luò )上的特定目錄裝載小應用程序代碼。

在設計一個(gè)類(lèi)裝載器的時(shí)候,應該滿(mǎn)足以下兩個(gè)條件:

  1. 對于相同的類(lèi)名,類(lèi)裝載器所返回的對象應該是同一個(gè)類(lèi)對象
  2. 如果類(lèi)裝載器CL1將裝載類(lèi)C的請求轉給類(lèi)裝載器CL2,那么對于以下的類(lèi)或接口,CL1和CL2應該返回同一個(gè)類(lèi)對象:a)S為C的直接超類(lèi);b)S為C的直接超接口;c)S為C的成員變量的類(lèi)型;d)S為C的成員方法或構建器的參數類(lèi)型;e)S為C的成員方法的返回類(lèi)型。

每個(gè)已經(jīng)裝載到JVM中的類(lèi)都隱式含有裝載它的類(lèi)裝載器的信息。類(lèi)方法getClassLoader 可以得到裝載這個(gè)類(lèi)的類(lèi)裝載器。一個(gè)類(lèi)裝載器認識的類(lèi)包括它的父裝載器認識的類(lèi)和它自己裝載的類(lèi),可見(jiàn)類(lèi)裝載器認識的類(lèi)是它自己裝載的類(lèi)的超集。注意我們可以得到類(lèi)裝載器的有關(guān)的信息,但是已經(jīng)裝載到JVM中的類(lèi)是不能更改它的類(lèi)裝載器的。

Java中的類(lèi)的裝載過(guò)程也就是代理裝載的過(guò)程。比如:Web瀏覽器中的JVM需要裝載一個(gè)小應用程序TestApplet。JVM調用小應用程序裝載器ACL(Applet ClassLoader)來(lái)完成裝載。ACL首先請求它的父裝載器, 即系統裝載器裝載TestApplet是否裝載了這個(gè)類(lèi), 由于TestApplet不在系統裝載器的裝載路徑中, 所以系統裝載器沒(méi)有找到這個(gè)類(lèi), 也就沒(méi)有裝載成功。接著(zhù)ACL自己裝載TestApplet。ACL通過(guò)網(wǎng)絡(luò )成功地找到了TestApplet.class 文件并將它導入到了JVM中。在裝載過(guò)程中, JVM發(fā)現TestAppet是從超類(lèi)java.applet.Applet繼承的。所以JVM再次調用ACL來(lái)裝載java.applet.Applet類(lèi)。ACL又再次按上面的順序裝載Applet類(lèi), 結果ACL發(fā)現他的父裝載器已經(jīng)裝載了這個(gè)類(lèi), 所以ACL就直接將這個(gè)已經(jīng)裝載的類(lèi)返回給了JVM , 完成了Applet類(lèi)的裝載。接下來(lái),Applet類(lèi)的超類(lèi)也一樣處理。最后, TestApplet及所有有關(guān)的類(lèi)都裝載到了JVM中。

四、結論

類(lèi)的動(dòng)態(tài)裝載機制是JVM的一項核心技術(shù), 也是容易被忽視而引起很多誤解的地方。本文介紹了JVM中類(lèi)裝載的原理、實(shí)現以及應用,尤其分析了ClassLoader的結構、用途以及如何利用自定義的ClassLoader裝載并執行Java類(lèi),希望能使讀者對JVM中的類(lèi)裝載有一個(gè)比較深入的理解。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Java學(xué)習筆記(適合面試前復習) - 瘋狂的菠菜 - JavaEye技術(shù)網(wǎng)站 - 文苑的...
一個(gè)Java程序的執行過(guò)程
深入Java虛擬機JVM類(lèi)加載初始化學(xué)習筆記
Java程序員從笨鳥(niǎo)到菜鳥(niǎo)之(九十三)深入java虛擬機(二)——類(lèi)加載器詳解(上)
JVM系列(一):JVM基本概念知識筆記
javac.exe、 java.exe、 java虛擬機三者之間的區別與聯(lián)系
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久