JVM 全稱是Java Virtual Machine ,Java 虛擬機,也就是在計算機上再虛擬一個計算機。java
這和咱們使用 VMWare 不同,那個虛擬的東西你是能夠看到的,這個JVM 你是看不到的,它存在內存中。程序員
計算機的基本構成是:運算器、控制器、存儲器、輸入和輸出設備。編程
JVM 也是有這成套的元素:框架
運算器 -固然是交給硬件CPU 還處理了jvm
爲了適應「一次編譯,隨處運行」的狀況,須要作一個翻譯動做,因而就用了JVM 本身的命令集。編程語言
這與彙編的命令集有點相似,每一種彙編命令集針對一個系列的CPU ,函數
好比8086 系列的彙編也是能夠用在8088 上的,可是就不能跑在8051 上。url
JVM 的命令集則是能夠處處運行的,由於JVM根據不一樣的CPU ,翻譯成不一樣的機器語言。spa
存儲器 - JVM 是一個內存中的虛擬機,那它的存儲器就是內存了。操作系統
咱們寫的全部類、常量、變量、方法都在內存中。
類加載器的做用是加載類文件到內存,
好比編寫一個HelloWord.java 程序,而後經過javac 編譯成class 文件,
那怎麼才能加載到內存中被執行呢?Class Loader 承擔的就是這個責任。
Class Loader 只管加載,只要符合文件結構就加載,
至於說能不能運行,則不是它負責的,那是由Execution Engine 負責的。
也叫作解釋器(Interpreter) ,負責解釋命令,提交操做系統執行。
本地接口的做用是融合不一樣的編程語言爲Java 所用,它的初衷是融合C/C++ 程序
目前該方法使用的已經比較少見了,由於如今的異構領域間的通訊很發達,
好比可使用Socket 通訊,也可使用Web Service 等等
4) Runtime data area 運行數據區
運行數據區是整個JVM 的重點。咱們全部寫的程序都被加載到這裏,以後纔開始運行
整個JVM 框架由加載器加載文件,而後執行器在內存中處理數據,須要與異構系統交互是能夠經過本地接口進行,一個完整的系統誕生了。
這個裝載工做是由jvm中的類裝載器完成的,類裝載器所作的工做實質是把類文件從硬盤讀取到內存中。
1) 系統類
2) 擴展類
3) 由程序員自定義的類
1) 隱式裝載。 程序在運行過程當中當碰到經過new 等方式生成對象時,
隱式調用類裝載器加載對應的類到jvm中。
2) 顯式裝載。 經過class.forname()等方法,顯式加載須要的類。
隱式加載與顯式加載的區別:
一個應用程序老是由n多個類組成,Java程序啓動時,並非一次把全部的類所有加載後再 運行.
它老是先把保證程序運行的基礎類一次性加載到jvm中,其它類等到jvm用到的時候再加載.
這樣的好處是節省了內存的開銷.
Java中的類裝載器實質上也是類,功能是把類載入jvm中.
值得注意的是jvm的類裝載器並非一個,而是三個。
爲何要有三個類加載器,一方面是分工,各自負責各自的區塊,另外一方面爲了實現委託模型。
Bootstrap Loader - 負責加載系統類(用C++語言寫的) 搜索路徑:sun.boot.class.path
|
ExtClassLoader - 負責加載擴展類 搜索路徑:java.ext.dirs
|
AppClassLoader - 負責加載應用類 搜索路徑:java.class.path
在這裏java採用了委託模型機制.
類裝載器有載入類的需求時,會先請示其Parent使用其搜索路徑幫忙載入,
若是Parent 找不到,那麼才由本身依照本身的搜索路徑搜索類。
1)在 JRE 運行的開始會將 Java 運行所須要的基本類採用預先加載( pre-loading )的方法所有加載要內存當中.
主要包括 JRE 的 rt.jar 文件裏面全部的 .class 文件
2) 當 java.exe 虛擬機開始運行之後,它會找到安裝在機器上的 JRE 環境,而後把控制權交給 JRE .
JRE 的類加載器會將 lib 目錄下的 rt.jar 基礎類別文件庫加載進內存.
3) 相對於預先加載,咱們在程序中須要使用本身定義的類的時候就要使用依需求加載方法
( load-on-demand ),就是在 Java 程序須要用到的時候再加載,以減小內存的消耗.
通常咱們都是調用系統的 類加載器來實現加載的,其實咱們是能夠本身定義類加載器的。
利用 Java 提供的 java.net.URLClassLoader 類就能夠實現。
try {
URL url = new URL( "file:/d:/test/lib/" );
URLClassLoader urlCL = new URLClassLoader( new URL[]{url});
Class c = urlCL.loadClass("TestClassA" );
TestClassA object = (TestClassA)c.newInstance();
object.method();
}catch (Exception e){
e.printStackTrace();
}
1)Java 的類加載器的工做原理:
當執行 java ***.class 的時候, java.exe 會幫助咱們找到 JRE
接着找到位於 JRE 內部的 jvm.dll ,這纔是真正的 Java 虛擬機器
最後加載動態庫,激活 Java 虛擬機器
虛擬機器激活之後,會先作一些初始化的動做,好比說讀取系統參數等。
一旦初始化動做完成以後,就會產生第一個類加載器―― Bootstrap Loader
Bootstrap Loader 是由 C++ 所撰寫而成
Bootstrap Loader 所作的初始工做中,除了一些基本的初始化動做以外,
最重要的就是加載 Launcher.java 之中的 ExtClassLoader ,並設定其 Parent 爲 null
表明其父加載器爲 BootstrapLoader
而後 Bootstrap Loader 再要求加載 Launcher.java 之中的 AppClassLoader ,
並設定其 Parent 爲以前產生的 ExtClassLoader 實體
*Launcher$ExtClassLoader.class 與 Launcher$AppClassLoader.class 都是由 Bootstrap Loader 所加載,
因此 Parent 和由哪一個類加載器加載沒有關係。
2)類加載器之間的關係
BootstrapLoader <---(Extends)----AppClassLoader <---(Extends)----ExtClassLoader
這三個加載器就構成咱們的 Java 類加載體系
3) 他們分別從如下的路徑尋找程序所須要的類:
BootstrapLoader : sun.boot.class.path
ExtClassLoader: java.ext.dirs
AppClassLoader: java.class.path
這三個系統參量能夠經過 System.getProperty() 函數獲得具體對應的路徑。