jdk <br> jdk(Java Development Kit)Java開發(fā)包,是Java開發(fā)人員用于編譯和調試程序的一套程序的集合。
創(chuàng)新互聯(lián)公司服務項目包括三河網站建設、三河網站制作、三河網頁制作以及三河網絡營銷策劃等。多年來,我們專注于互聯(lián)網行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構等提供互聯(lián)網行業(yè)的解決方案,三河網站推廣取得了明顯的社會效益與經濟效益。目前,我們服務的客戶以成都為中心已經輻射到三河省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!
jre <br> jre(Java Runtime Evironment)Java運行時環(huán)境,是運行Java程序的平臺,所有的Java程序必須在這個平臺中才能執(zhí)行。
jvm <br> jvm(Java Virtual Machine)Java虛擬機,是用代碼虛擬出來的計算機,模擬執(zhí)行計算機的各項功能,它有自己的硬件架構,如:處理器、堆棧、寄存器等,還有自己的一套指令系統(tǒng),在不同的操作系統(tǒng)上都可以安裝JVM,從而實現(xiàn)Java程序在不同的操作系統(tǒng)上都能執(zhí)行,JVM就是為實現(xiàn)Java的跨平臺特性。
我們執(zhí)行Java程序開發(fā)出來后,需要先編譯再執(zhí)行,JVM就負責加載類的過程。 <br> 類加載的過程分為:
加載
驗證
準備
解析
初始化
下面詳細介紹下這幾個過程:
加載 <br> 在加載類的過程要完成:
根據類的全名限定符,獲取class二進制流,這個流可以從磁盤上的class、jar文件獲得,也可以從網絡中獲得。
將類的靜態(tài)存儲結構轉化為方法區(qū)的運行時動態(tài)存儲結構
在內存的堆中生成對應的java.lang.Class對象,作為方法區(qū)的入口
驗證 <br> 加載類完成后,就進入了驗證過程,這個過程保證了前面生成的Class對象中的信息,不會危害JVM的安全。 <br> 需要驗證的方面有:
文件格式驗證,是要驗證字節(jié)流是否符合Class文件格式的規(guī)范,并且能被當前版本的虛擬機處理。如驗證魔數(shù)是否0xCAFEBABE;主、次版本號是否正在當前虛擬機處理范圍之內;常量池的常量中是否有不被支持的常量類型等等,該驗證階段的主要目的是保證輸入的字節(jié)流能正確地解析并存儲于方法區(qū)中,經過這個階段的驗證后,字節(jié)流才會進入內存的方法區(qū)中存儲,所以后面的三個驗證階段都是基于方法區(qū)的存儲結構進行的。
元數(shù)據驗證,是對字節(jié)碼描述的信息進行語義分析,以保證其描述的信息符合Java語言規(guī)范的要求??赡馨ǖ尿炞C如:這個類是否有父類;這個類的父類是否繼承了不允許被繼承的類;如果這個類不是抽象類,是否實現(xiàn)了其父類或接口中要求實現(xiàn)的所有方法。
字節(jié)碼驗證,主要工作是進行數(shù)據流和控制流分析,保證被校驗類的方法在運行時不會做出危害虛擬機安全的行為。如果一個類方法體的字節(jié)碼沒有通過字節(jié)碼驗證,那肯定是有問題的;但如果一個方法體通過了字節(jié)碼驗證,也不能說明其一定就是安全的。
符號引用驗證,發(fā)生在虛擬機將符號引用轉化為直接引用的時候,這個轉化動作將在“解析階段”中發(fā)生。驗證符號引用中通過字符串描述的權限定名是否能找到對應的類;在指定類中是否存在符合方法字段的描述符及簡單名稱所描述的方法和字段;符號引用中的類、字段和方法的訪問性(private、protected、public、default)是否可被當前類訪問。
準備 <br> 準備階段會在方法區(qū)中為類的靜態(tài)變量分配內存,并賦給默認值。
public static int count = 100;
如:上面的count變量在準備階段會賦值為0,在初始化時再賦值為100;
解析 <br> 解析階段是虛擬機將常量池內的符號引用替換為直接引用的過程。
符號引用(Symbolic Reference) <br> 符號引用以一組符號來描述所引用的目標,符號可以是任何形式的字面量,只要使用時能無歧義地定位到目標即可。符號引用與虛擬機實現(xiàn)的內存布局無關,引用的目標并不一定已經加載到內存中。
直接引用(Direct Reference) <br> 直接引用可以是直接指向目標的指針、相對偏移量或是一個能間接定位到目標的句柄。直接引用是與虛擬機實現(xiàn)的內存布局相關的,如果有了直接引用,那么引用的目標必定已經在內存中存在。
初始化 <br> 類初始化是類加載過程的最后一步,前面的類加載過程,除了在加載階段用戶應用程序可以通過自定義類加載器參與之外,其余動作完全由虛擬機主導和控制。到了初始化階段,才真正開始執(zhí)行類中定義的Java程序代碼。 <br> 初始化階段是執(zhí)行類構造器 <clinit> ()方法的過程。 <clinit> ()方法是由編譯器自動收集類中的所有類變量的賦值動作和靜態(tài)語句塊(static{}塊)中的語句合并產生的。
那么何時執(zhí)行初始化呢?
創(chuàng)建類的實例
訪問類的靜態(tài)變量(除常量外,final修飾的) 原因:常量一種特殊的變量,因為編譯器把他們當作值而不是屬性來對待。
訪問類的靜態(tài)方法
反射如(Class.forName("com.test.Person"))
當初始化一個類時,發(fā)現(xiàn)其父類還未初始化,則先調用父類的初始化
虛擬機啟動時,定義了main()方法的那個類先初始化
了解了類的加載機制,我們來看一道面試題:
public class MySingleton {
private static MySingleton singleton = new MySingleton();
public static int count1 = 0;
public static int count2;
private MySingleton(){
count1++;
count2++;
}
public static MySingleton getInstance(){
return singleton;
}
public static void main(String[] args) {
MySingleton singleton = MySingleton.getInstance();
System.out.println("count1-->"+MySingleton.count1);
System.out.println("count2-->"+MySingleton.count2);
}
}
上面的結果,大多數(shù)同學可能認為兩個靜態(tài)變量都是1,結果比較意外:
count1-->0
count2-->1
這是為什么呢?下面我們來分析下:
首先我們知道在類的準備階段會為靜態(tài)變量賦默認值: <br> singleton = null; count1 = 0; count2 = 0;
當調用類的靜態(tài)方法getInstance后,引發(fā)類的初始化,先執(zhí)行new MySingleton() 調用構造方法,這時: <br> count1 = 1; count2 = 1;
繼續(xù)初始化,為變量賦值,count1賦值為0,count2沒有賦值就保留值1,結果就是: <br> count1 = 0; count2 = 1;
JVM是代碼模擬的計算機,有自己的硬件和軟件,JVM能實現(xiàn)Java類的加載和運行,具體加載過程有:加載、驗證、準備、解析、初始化5個步驟組成。
本文名稱:好程序員Java分享JVM類加載機制
文章鏈接:http://www.rwnh.cn/article28/pgsscp.html
成都網站建設公司_創(chuàng)新互聯(lián),為您提供Google、虛擬主機、品牌網站制作、服務器托管、外貿建站、網站收錄
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)