您好,登錄后才能下訂單哦!
今天小編給大家分享一下JVM加載class文件的原理機制是什么的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
JVM是Java Virtual Machine(Java虛擬機)的縮寫,JVM是一種用于計算設備的規范,它是一個虛構出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現的。
Java語言的一個非常重要的特點就是與平臺的 無關性。而使用Java虛擬機是實現這一特點的關鍵。一般的高級語言如果要在不同的平臺上運行,至少需要編譯成不同的目標代碼。而引入Java語言虛擬機后,Java語言在不同平臺上運行時不需要重新編譯。Java語言使用Java虛擬機屏蔽了與平臺相關的信息,使得Java語言編譯程序只需生成在Java虛擬機上運行的目標代碼(字節碼),就可以在多種平臺上不加修改的運行。Java虛擬機在執行字節碼時,把字節碼解釋成具體平臺上的及其指令執行。這就是Java能夠“一次編譯,到處運行”的原因。
由圖可以看出,JVM是運行在操作系統之上的,它與硬件沒有直接的交互。
1. 類加載器 Class Loader
類加載器的作用是加載類文件到內存,比如編寫一個HelloWorld.java程序,然后通過javac編譯生成class文件。由Class Loader將class文件加載到內存中。但是Class Loader加載class文件有格式要求。
注意:Class Loader只管加載,只要符合文件結構就加載,至于能不能運行,是由Execution Engine負責。
2. 執行引擎 Exexution Engine
執行引擎也叫作解釋器,負責解釋命令,提交操作系統執行。
3. 本地接口 Native Interface
本地接口的作用是為了融合不同的編程語言為Java所用。它的初衷是為了融合C/C++程序,Java誕生的時候是C/C++橫行的時候,要想立足,必須要有一個聰明的、睿智的調用C/C++程序,于是就在內存中專門開辟了一塊區域處理標記為native的代碼,它的具體做法是Native Method Stack中登記native方法,在Execution Engine執行時加載加載native libraries。目前該方法只有在與硬件有關的應用中才會使用,在企業級應用中已經比較少見,因為現在的異構領域間的通信很發達,比如可以使用Socket通信,也可以使用WebService等。
4. 運行數據區 Runtime data area
運行數據區使整個JVM的重點。我們所寫的程序都被加載到這里,之后才開始運行,Java生態系統如此的繁榮,得益于該區域的優良自治。
1. Java中的所有類,必須被裝載到JVM中才能運行,這個裝載工作是由JVM中的類裝載器完成的,類裝載器所做的工作實質是把類文件從硬盤讀取到內存中,作用就是在運行時加載類。
Java類加載器基于三個機制:委托、可見性和單一性。
(1)委托機制是指加載一個類的請求交給父類加載器,如果這個父類加載器不能夠找到或加載這個類,那么再加載它。
(2)可見性的原理是子類的加載器可以看見所有的父類加載器加載的類,而父類加載器看不到子類加載器加載的類。
(3)單一性原理是指一個類僅被加載一次,這是由委托機制確保子類加載器不會再次加載父類加載器加載過的類。
2. Java中的類大致分為三種:
(1)系統類
(2)擴展類
(3)由程序員自定義的類
3. 類裝載有兩種方式
(1)隱式裝載:
程序在運行過程中當碰到通過new等方式生成類或者子類對象、使用類或者子類的靜態域時,隱式調用類加載器加載對應的的類到JVM中。
(2)顯式裝載:
通過調用Class.forName()或者ClassLoader.loadClass(className)等方法,顯式加載需要的類。
4. 類加載的動態性體現
一個應用程序總是由n多個類組成,Java程序啟動時,并不是一次把所有的類全部加載再運行,他總是把保證程序運行的基礎類一次性加載到JVM中,其他類等到JVM用到的時候再加載,這樣是為了節省內存的開銷,因為Java最早就是為嵌入式系統而設計的,內存寶貴,而用到時再加載這也是Java動態性的一種體現。
5. Java類加載器
Java中的類加載器實質上也是也是類,功能是把類加載入JVM中,值得注意的是JVM的類加載器有三個,原因有:一方面是為了分工明確,各自負責各自的區塊,另一方面為了實現委托模型。
層次結構如下:
BootStrap Loader(引導類加載器) ----- 負責加載系統類
ExtClassLoader(擴展類加載器) ----- 負責加載擴展類
AppClassLoade(應用類加載器)r ----- 負責加載應用類
6. 類加載器之間如何協調工作的
Java中有三個類加載器,碰到一個類需要加載時,Java采用委托模型機制來協調和區分該由哪個類加載器完成。簡單來說就是,“類裝載器有載入類的需求時,會先請示其Parent使用其搜索路徑幫忙載入”,如果Parent找不到,那么才由自己依照自己的搜索路徑搜索類。
實例一:
package ClassLoaderTest; public class ClassLoaderTest { public static void main(String[] args) { ClassLoader c1 = ClassLoaderTest.class.getClassLoader(); System.out.println(c1); ClassLoader c1Parent = c1.getParent(); System.out.println(c1Parent); ClassLoader c1Root = c1Parent.getParent(); System.out.println(c1Root); } }
執行結果:
可以看出ClassLoaderTest是由AppClassLoader加載器加載的。AppClassLoader的Parent加載器是ExtClassLoader。但是ExtClassLoader的Parent是null,在Java中是無法獲取的。
實例二:
public class Test2 { public void test(){ System.out.println(Test2.class); System.out.println(this.getClass()); System.out.println(Test2.class.getClassLoader()); } } public class Test1 { public static void main(String[] args) { System.out.println(Test1.class.getClassLoader()); Test2 test2 = new Test2(); test2.test(); } }
執行結果:
7. 預先加載和依需求加載
Java運行環境為了優化系統,提高程序的執行速度,在JRE運行的開始會將Java運行所需要的基本類采用預先加載(pre-loading)的方法全部加載到內存當中,因為這些單元在Java程序運行的過程當中要經常使用的,主要包括JRE的rt.jar文件里面所有的.class文件。
當java.exe虛擬機開始運行以后,它會找到安裝在機器上的JRE環境,然后把控制權交給JRE,JRE的類加載器會自動將lib目錄下的rt.jar基礎類別文件庫加載進內存,這些文件是Java程序執行所必需的,所以系統在開始就將這些文件加載,避免以后的多次IO操作,從而提高程序執行效率。然而我們在程序中需要使用自定義的類的時候就要使用依需求加載(load-on-demand)的方式,就是在Java程序需要用到的時候再加載,以減少內存的消耗。
8. ClassLoader中一些 重要的方法
9.什么地方適用類加載器
最經典的例子就是AppletClassLoader,他被用來加載Applet使用的類,而Applet大部分是在網上使用,而非本地的操作系統使用。使用不同的類加載器,你可以從不同的源地址加載同一個類,它們被視為不同的類。J2EE使用多個類加載器加載不同地方的類,例如War文件由Web-app類加載器加載,而EJB-JAR中的類由另外的類加載器加載。有些服務器也支持熱部署,這是由類加載器實現。你也可以使用類加載器來加載數據庫或者其他持久層的數據。
10. 類加載器的階層體系
Java類加載器的工作原理:
當執行Java的.class文件的時候,java.exe會幫助我們找到jRE,接著找到JRE內部的jcm.dll,這才是真正的Java虛擬機器,最后加載動態庫,激活Java虛擬機器。虛擬機激活以后,會先做一些初始化的動作,比如說讀取系統參數等。一旦初始化動作完成后,就會產生第一個類加載器-----Bootstrap Loader,Bootstrap Loader是由C++撰寫而成,這個Bootstrap所做的初始工作中,除了一些基本的初始化動作之外,最重要的就是加載Launcher.java之中的ExtClassLoader,并設定其parent為null,代表其父加載器為BootstrapLoader。然后Bootstrap loader再要求加載Launcher.java之中的AppClassLoader,并設定其parent為之前產生的ExtClassLoader實體。這兩個類加載器都是以靜態類的形式存在的。注意:Launcher E x t C l a s s L o a d e r . c l a s s 與 L a u n c h e r ExtClassLoader.class與Launcher ExtClassLoader.class與LauncherAppClassLoader.class都是由Bootstrap Loader所加載,所以Parent和由哪個類加載器加載沒有關系。
三者之間的關系:
Bootstrap Loader <—(extends)-----ExtClassLoader <—(extends)—AppClassLoader
這三個類加載器構成了Java的類加載體系。它們分別從以下的路徑尋找程序所需要的類:
Bootstrap Loader:sun.boot.class.path
ExtClassLoader:java.ext.dirs
AppClassLoader:java.class.path
這三個參數可以通過System.getProperty()函數得到具體對應的路徑。
以上就是“JVM加載class文件的原理機制是什么”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。