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

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 深入解析JVM對dll文件和對類的裝載過程

深入解析JVM對dll文件和對類的裝載過程

2020-03-01 11:2080197675 JAVA教程

這篇文章主要介紹了JVM對dll文件的裝載和對類的裝載過程,針對Java在Windows下的一些運行情況作出講解,需要的朋友可以參考下

JVM的對dll文件的裝載過程

操作系統裝入JVM是通過jdk中Java.exe來完成,通過下面4步來完成JVM環境.

1.創建JVM裝載環境和配置

2.裝載JVM.dll

3.初始化JVM.dll并掛界到JNIENV(JNI調用接口)實例

4.調用JNIEnv實例裝載并處理class類。

一.JVM裝入環境,JVM提供的方式是操作系統的動態連接文件.
    既然是文件那就一個裝入路徑的問題,Java是怎么找這個路徑的呢?當你在調用Java test的時候,操作系統會在path下在你的Java.exe程序,Java.exe就通過下面一個過程來確定JVM的路徑和相關的參數配置了.下面基于Windows的實現的分析.

    首先查找jre路徑,Java是通過GetApplicationHome api【該方法存在于java_md.c】來獲得當前的Java.exe絕對路徑。
    例如 c:j2sdk1.4.2_09inJava.exe,那么它會截取到絕對路徑c:j2sdk1.4.2_09,判斷c:j2sdk1.4.2_09inJava.dll文件是否存在,如果存在就把c:j2sdk1.4.2_09作為jre路徑,如果不存在則判斷c:j2sdk1.4.2_09jreinJava.dll是否存在,如果存在這c:j2sdk1.4.2_09jre作為jre路徑.如果不存在調用GetPublicJREHome查HKEY_LOCAL_MACHINESoftwareJavaSoftJava Runtime Environment“當前JRE版本號”JavaHome的路徑為jre路徑。
   備注獲取當前jre路徑的方法為System.out.println(System.getProperty("java.home"));

   然后裝載JVM.cfg文件JRE路徑+lib+ARCH(CPU構架)+JVM.cfgARCH(CPU構架)的判斷是通過Java_md.c中GetArch函數判斷的,該函數中windows平臺只有兩種情況:WIN64的‘ia64',其他情況都為‘i386'。以我的為例:C:j2sdk1.4.2_09jrelibi386JVM.cfg.主要的內容如下: 

  •   -client KNOWN  
  •   -server KNOWN 
  •   -hotspot ALIASED_TO -client  
  •   -classic WARN
  •   -native ERROR
  •   -green ERROR  

  在我們的jdk目錄中jreinserver和jreinclient都有JVM.dll文件存在,而Java正是通過JVM.cfg配置文件來管理這些不同版本的JVM.dll的.通過文件我們可以定義目前jdk中支持那些JVM,前面部分(client)是JVM名稱,后面是參數,KNOWN表示JVM存在,ALIASED_TO表示給別的JVM取一個別名,WARN表示不存在時找一個JVM替代,ERROR表示不存在拋出異常.

  在運行Java XXX是,Java.exe會通過CheckJVMType來檢查當前的JVM類型,Java可以通過兩種方式來指定具體的JVM類型,
  第一種按照JVM.cfg文件中的JVM名稱指定。
  第二種方法是直接指定,它們執行的方法分別是“Java -J”、“Java -XXaltJVM=”或“Java -J-XXaltJVM=”。
  如果是第一種參數傳遞方式,CheckJVMType函數會取參數‘-J'后面的JVM名稱,然后從已知的JVM配置參數中查找如果找到同名的則去掉該JVM名稱前的‘-'直接返回該值;
  而第二種方法,會直接返回“-XXaltJVM=”或“-J-XXaltJVM=”后面的JVM類型名稱;如果在運行Java時未指定上面兩種方法中的任一一種參數,CheckJVMType會取配置文件中第一個配置中的JVM名稱,去掉名稱前面的‘-'返回該值。CheckJVMType函數的這個返回值會在下面的函數中匯同jre路徑組合成JVM.dll的絕對路徑。
  如果沒有指定這會使用JVM.cfg中第一個定義的JVM.可以通過set _Java_LAUNCHER_DEBUG=1在控制臺上測試.

  最后獲得JVM.dll的路徑,JRE路徑+in+JVM類型字符串+JVM.dll就是JVM的文件路徑了,但是如果在調用Java程序時用-XXaltJVM=參數指定的路徑path,就直接用path+JVM.dll文件做為JVM.dll的文件路徑.

二:裝載JVM.dll

    通過第一步已經找到了JVM的路徑,Java通過LoadJavaVM來裝入JVM.dll文件.裝入工作很簡單就是調用Windows API函數:

    LoadLibrary裝載JVM.dll動態連接庫.然后把JVM.dll中的導出函數JNI_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs掛接到   InvocationFunctions變量的CreateJavaVM和GetDefaultJavaVMInitArgs函數指針變量上。JVM.dll的裝載工作宣告完成。

三:初始化JVM,獲得本地調用接口
      這樣就可以在Java中調用JVM的函數了.調用InvocationFunctions->CreateJavaVM也就是JVM中   JNI_CreateJavaVM方法獲得JNIEnv結構的實例.

四:運行Java程序.

    Java程序有兩種方式一種是jar包,一種是class. 運行jar,Java -jar XXX.jar運行的時候,Java.exe調用GetMainClassName函數,該函數先獲得JNIEnv實例然后調用Java類Java.util.jar.JarFileJNIEnv中方法getManifest()并從返回的Manifest對象中取getAttributes("Main-Class")的值即jar包中文件:META-INF/MANIFEST.MF指定的Main-Class的主類名作為運行的主類。之后main函數會調用Java.c中LoadClass方法裝載該主類(使用JNIEnv實例的FindClass)。main函數直接調用Java.c中LoadClass方法裝載該類。如果是執行class方法。main函數直接調用Java.c中LoadClass方法裝載該類。

    然后main函數調用JNIEnv實例的GetStaticMethodID方法查找裝載的class主類中。“public static void main(String[] args)”方法,并判斷該方法是否為public方法,然后調用JNIEnv實例的 CallStaticVoidMethod方法調用該Java類的main方法。

JVM的類裝載
一、引言
      Java虛擬機(JVM)的類裝載就是指將包含在類文件中的字節碼裝載到JVM中, 并使其成為JVM一部分的過程。JVM的類動態裝載技術能夠在運行時刻動態地加載或者替換系統的某些功能模塊, 而不影響系統其他功能模塊的正常運行。本文將分析JVM中的類裝載系統,探討JVM中類裝載的原理、實現以及應用。
二、Java虛擬機的類裝載實現與應用
2.1  裝載過程簡介
       所謂裝載就是尋找一個類或是一個接口的二進制形式并用該二進制形式來構造代表這個類或是這個接口的class對象的過程,其中類或接口的名稱是給定了的。當然名稱也可以通過計算得到,但是更常見的是通過搜索源代碼經過編譯器編譯后所得到的二進制形式來構造。
      在Java中,類裝載器把一個類裝入Java虛擬機中,要經過三個步驟來完成:裝載、鏈接和初始化,其中鏈接又可以分成校驗、準備和解析三步,除了解析外,其它步驟是嚴格按照順序完成的,各個步驟的主要工作如下:

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

2.2  裝載的實現

     JVM中類的裝載是由ClassLoader和它的子類來實現的,Java ClassLoader 是一個重要的Java運行時系統組件。它負責在運行時查找和裝入類文件的類。
     在Java中,ClassLoader是一個抽象類,它在包java.lang中,可以這樣說,只要了解了在ClassLoader中的一些重要的方法,再結合上面所介紹的JVM中類裝載的具體的過程,對動態裝載類這項技術就有了一個比較大概的掌握,這些重要的方法包括以下幾個:
     ①loadCass方法  loadClass(String name ,boolean resolve)其中name參數指定了JVM需要的類的名稱,該名稱以包表示法表示,如Java.lang.Object;resolve參數告訴方法是否需要解析類,在初始化類之前,應考慮類解析,并不是所有的類都需要解析,如果JVM只需要知道該類是否存在或找出該類的超類,那么就不需要解析。這個方法是ClassLoader 的入口點。
     ②defineClass方法  這個方法接受類文件的字節數組并把它轉換成Class對象。字節數組可以是從本地文件系統或網絡裝入的數據。它把字節碼分析成運行時數據結構、校驗有效性等等。
     ③findSystemClass方法  findSystemClass方法從本地文件系統裝入文件。它在本地文件系統中尋找類文件,如果存在,就使用defineClass將字節數組轉換成 Class對象,以將該文件轉換成類。當運行Java應用程序時,這是JVM 正常裝入類的缺省機制。
     ④resolveClass方法  resolveClass(Class c)方法解析裝入的類,如果該類已經被解析過那么將不做處理。當調用loadClass方法時,通過它的resolve 參數決定是否要進行解析。
     ⑤findLoadedClass方法  當調用loadClass方法裝入類時,調用findLoadedClass 方法來查看ClassLoader是否已裝入這個類,如果已裝入,那么返回Class對象,否則返回NULL。如果強行裝載已存在的類,將會拋出鏈接錯誤。
2.3  裝載的應用
      一般來說,我們使用虛擬機的類裝載時需要繼承抽象類java.lang.ClassLoader,其中必須實現的方法是loadClass(),對于這個方法需要實現如下操作:(1) 確認類的名稱;(2) 檢查請求要裝載的類是否已經被裝載;(3) 檢查請求加載的類是否是系統類;(4) 嘗試從類裝載器的存儲區獲取所請求的類;(5) 在虛擬機中定義所請求的類;(6) 解析所請求的類;(7) 返回所請求的類。
      所有的Java 虛擬機都包括一個內置的類裝載器,這個內置的類庫裝載器被稱為根裝載器(bootstrap ClassLoader)。根裝載器的特殊之處是它只能夠裝載在設計時刻已知的類,因此虛擬機假定由根裝載器所裝載的類都是安全的、可信任的,可以不經過安全認證而直接運行。當應用程序需要加載并不是設計時就知道的類時,必須使用用戶自定義的裝載器(user-defined ClassLoader)。下面我們舉例說明它的應用。

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

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

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

深入解析JVM對dll文件和對類的裝載過程

圖2  Java類裝載的代理結構
下面針對各種類裝載器分別進行詳細的說明。
      根(Bootstrap) 裝載器:該裝載器沒有父裝載器,它是JVM實現的一部分,從sun.boot.class.path裝載運行時庫的核心代碼。
      擴展(Extension) 裝載器:繼承的父裝載器為根裝載器,不像根裝載器可能與運行時的操作系統有關,這個類裝載器是用純Java代碼實現的,它從java.ext.dirs (擴展目錄)中裝載代碼。
      系統(System or Application) 裝載器:裝載器為擴展裝載器,我們都知道在安裝JDK的時候要設置環境變量(CLASSPATH ),這個類裝載器就是從java.class.path(CLASSPATH 環境變量)中裝載代碼的,它也是用純Java代碼實現的,同時還是用戶自定義類裝載器的缺省父裝載器。
      小應用程序(Applet) 裝載器: 裝載器為系統裝載器,它從用戶指定的網絡上的特定目錄裝載小應用程序代碼。
在設計一個類裝載器的時候,應該滿足以下兩個條件:
     對于相同的類名,類裝載器所返回的對象應該是同一個類對象
     如果類裝載器CL1將裝載類C的請求轉給類裝載器CL2,那么對于以下的類或接口,CL1和CL2應該返回同一個類對象:a)S為C的直接超類;b)S為C的直接超接口;c)S為C的成員變量的類型;d)S為C的成員方法或構建器的參數類型;e)S為C的成員方法的返回類型。
      每個已經裝載到JVM中的類都隱式含有裝載它的類裝載器的信息。類方法getClassLoader 可以得到裝載這個類的類裝載器。一個類裝載器認識的類包括它的父裝載器認識的類和它自己裝載的類,可見類裝載器認識的類是它自己裝載的類的超集。注意我們可以得到類裝載器的有關的信息,但是已經裝載到JVM中的類是不能更改它的類裝載器的。
Java中的類的裝載過程也就是代理裝載的過程。比如:Web瀏覽器中的JVM需要裝載一個小應用程序TestApplet。JVM調用小應用程序裝載器ACL(Applet ClassLoader)來完成裝載。ACL首先請求它的父裝載器, 即系統裝載器裝載TestApplet是否裝載了這個類, 由于TestApplet不在系統裝載器的裝載路徑中, 所以系統裝載器沒有找到這個類, 也就沒有裝載成功。接著ACL自己裝載TestApplet。ACL通過網絡成功地找到了TestApplet.class 文件并將它導入到了JVM中。在裝載過程中, JVM發現TestAppet是從超類java.applet.Applet繼承的。所以JVM再次調用ACL來裝載 java.applet.Applet類。ACL又再次按上面的順序裝載Applet類, 結果ACL發現他的父裝載器已經裝載了這個類, 所以ACL就直接將這個已經裝載的類返回給了JVM , 完成了Applet類的裝載。接下來,Applet類的超類也一樣處理。最后, TestApplet及所有有關的類都裝載到了JVM中。
四、結論
      類的動態裝載機制是JVM的一項核心技術, 也是容易被忽視而引起很多誤解的地方。本文介紹了JVM中類裝載的原理、實現以及應用,尤其分析了ClassLoader的結構、用途以及如何利用自定義的ClassLoader裝載并執行Java類,希望能使讀者對JVM中的類裝載有一個比較深入的理解。

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 粉嫩欧美一区二区三区高清影视 | 欧美在线视频网站 | 国产成人综合视频 | 日韩一区二区视频 | 欧美中文字幕在线 | 亚洲欧美在线视频 | 日韩福利| 欧美激情精品久久久久久 | 免费观看黄视频 | 中文二区 | 婷婷激情五月 | 精品国产乱码久久久久久影片 | 中文字幕在线免费视频 | 欧美一区久久 | 小视频免费在线观看 | 国产精品久久久久一区二区三区 | 成人婷婷网色偷偷亚洲男人的天堂 | 精品亚洲综合 | 秋霞精品| 久久精品视频网站 | 亚洲激情视频在线 | 久久久久亚洲精品 | 免费观看一级特黄欧美大片 | 精品久久久久久久久久久久久久 | 日本免费视频 | 日韩精品免费在线视频 | 美女视频一区 | 精品福利网站 | 成人精品99 | 亚洲网色| 国产精品久久久久久久久久妞妞 | 成人激情毛片 | 日本在线视频一区二区 | 精品国产乱码久久久久久牛牛 | 久久精品免费 | 亚洲美腿 欧美 激情 另类 | 欧美一区三区 | 麻豆国产免费 | 成人午夜影院 | 亚洲国产成人av | 亚洲精品在线观看av |