先來看下百度百科的解釋:java
JVM 是 Java Virtual Machine(Java 虛擬機)的縮寫,JVM 是一種用於計算設備的規範,它是一個虛構出來的計算機,是經過在實際的計算機上仿真模擬各類計算機功能來實現的。數據庫
晦澀難懂有沒有,簡單理解就是說虛擬機是物理機的軟件實現。編程
Java 的設計理念是 WORA(Write Once Run Anywhere,一次編寫處處運行)。編譯器將 Java 文件編譯爲 Java .class 文件,而後將 .class 文件輸入到 JVM 中,JVM 執行類文件的加載和執行,最後轉變成機器能夠識別的機器碼進行最終的操做。數組
JVM體系結構圖緩存
一、加載安全
加載指的是將類的class文件讀入到內存,併爲之建立一個java.lang.Class對象,也就是說,當程序中使用任何類時,系統都會爲之創建一個java.lang.Class對象。網絡
類的加載由類加載器完成,類加載器一般由JVM提供,這些類加載器也是前面全部程序運行的基礎,JVM提供的這些類加載器一般被稱爲系統類加載器。除此以外,開發者能夠經過繼承ClassLoader基類來建立本身的類加載器。數據結構
經過使用不一樣的類加載器,能夠從不一樣來源加載類的二進制數據,一般有以下幾種來源。jvm
2.連接
當類被加載以後,系統爲之生成一個對應的Class對象,接着將會進入鏈接階段,連接階段負責把類的二進制數據合併到JRE中。類連接又可分爲以下3個階段。佈局
1)驗證:驗證階段用於檢驗被加載的類是否有正確的內部結構,並和其餘類協調一致。Java是相對C++語言是安全的語言,例如它有C++不具備的數組越界的檢查。這自己就是對自身安全的一種保護。驗證階段是Java很是重要的一個階段,它會直接的保證應用是否會被惡意入侵的一道重要的防線,越是嚴謹的驗證機制越安全。驗證的目的在於確保Class文件的字節流中包含信息符合當前虛擬機要求,不會危害虛擬機自身安全。其主要包括四種驗證,文件格式驗證,元數據驗證,字節碼驗證,符號引用驗證。
2)準備:類準備階段負責爲類的靜態變量分配內存,並設置默認初始值。
3)解析:將類的二進制數據中的符號引用替換成直接引用。說明一下:符號引用:符號引用是以一組符號來描述所引用的目標,符號能夠是任何的字面形式的字面量,只要不會出現衝突可以定位到就行。佈局和內存無關。直接引用:是指向目標的指針,偏移量或者可以直接定位的句柄。該引用是和內存中的佈局有關的,而且必定加載進來的。
3.初始化
初始化是爲類的靜態變量賦予正確的初始值,準備階段和初始化階段看似有點矛盾,實際上是不矛盾的,若是類中有語句:private static int a = 10,它的執行過程是這樣的,首先字節碼文件被加載到內存後,先進行連接的驗證這一步驟,驗證經過後準備階段,給a分配內存,由於變量a是static的,因此此時a等於int類型的默認初始值0,即a=0,而後到解析(後面在說),到初始化這一步驟時,才把a的真正的值10賦給a,此時a=10。
負責加載class文件,class文件在文件開頭由特定的文件標識,將class文件字節碼內容加載到內存中,並將這些內容轉換成方法區中的運行時數據結構而且ClassLoader只負責class文件的加載,至於它是否能夠運行,則由Execution Engine(執行引擎)決定。
四種類加載器
虛擬機自帶的加載器
Bootstrap ClassLoader是由C/C++編寫的,它自己是虛擬機的一部分,因此它並非一個JAVA類,也就是沒法在java代碼中獲取它的引用,JVM啓動時經過Bootstrap類加載器加載rt.jar等核心jar包中的class文件,以前的int.class,String.class都是由它加載。而後呢,咱們前面已經分析了,JVM初始化sun.misc.Launcher並建立Extension ClassLoader和AppClassLoader實例。並將ExtClassLoader設置爲AppClassLoader的父加載器。Bootstrap沒有父加載器,可是它卻能夠做用一個ClassLoader的父加載器。好比ExtClassLoader。這也能夠解釋以前經過ExtClassLoader的getParent方法獲取爲Null的現象
System.out.println(new Object().getClass().getClassLoader()); //這也就是爲何這段代碼打印出結果爲null的緣由
ExtClassLoader稱爲擴展類加載器,主要負責加載Java的擴展類庫,默認加載JAVA_HOME/jre/lib/ext/目錄下的全部jar包或者由java.ext.dirs系統屬性指定的jar包.放入這個目錄下的jar包對AppClassLoader加載器都是可見的(由於ExtClassLoader是AppClassLoader的父加載器,而且Java類加載器採用了委託機制).
AppClassLoader應用類加載器,又稱爲系統類加載器,負責在JVM啓動時,加載來自在命令java中的classpath或者java.class.path系統屬性或者CLASSPATH操做系統屬性所指定的JAR類包和類路徑.
public class AppClassLoaderTest { public static void main(String[] args) { ClassLoader classLoader = Test.class.getClassLoader(); System.out.println(classLoader); System.out.println(classLoader.getParent()); } private static class Test { } } //執行結果以下 sun.misc.Launcher$AppClassLoader@73d16e93 sun.misc.Launcher$ExtClassLoader@15db9742 //從上面的運行結果能夠得知AppClassLoader的父加載器是ExtClassLoader
用戶自定義的加載器
JVM的類加載機制主要有以下3種:
雙親委派機制的做用
一、防止重複加載同一個.class。經過委託去向上面問一問,加載過了,就不用再加載一遍。保證數據安全。 二、保證核心.class不能被篡改。經過委託方式,不會去篡改核心.class,即便篡改也不會去加載,即便加載也不會是同一個.class對象了。不一樣的加載器加載同一個.class也不是同一個Class對象。這樣保證了Class執行安全。