北京高端網(wǎng)站建設(shè)價(jià)格sem優(yōu)化托管公司
1.JVM概述
1.1為什么要學(xué)習(xí)JVM
?? 通過(guò)學(xué)習(xí)JVM (? java Virtual Machine )可以幫助我們理解java程序運(yùn)行的過(guò)程,了解虛擬機(jī)中各種機(jī)制的實(shí)現(xiàn)原理。為后期寫(xiě)出優(yōu)質(zhì)的代碼做好準(zhǔn)備,為向更高的層次提升打好基礎(chǔ)。
1.2虛擬機(jī)
? ? ?? 虛擬機(jī)的本質(zhì)就是在windows中,虛擬一個(gè)運(yùn)行的環(huán)境,分為系統(tǒng)虛擬機(jī)比如:VMware和程序虛擬機(jī)。程序虛擬機(jī)的典型代表就是java虛擬機(jī),虛擬機(jī)是專(zhuān)門(mén)為執(zhí)行某個(gè)單個(gè)計(jì)算機(jī)程序而設(shè)計(jì)。在java虛擬機(jī)中執(zhí)行的指令我們稱(chēng)為java字節(jié)碼指令。
1.3JVM作用
???? (1)負(fù)責(zé)將字節(jié)碼加載到內(nèi)存中(運(yùn)行時(shí)數(shù)據(jù)區(qū))
???? (2)負(fù)責(zé)存儲(chǔ)數(shù)據(jù)
???? (3)把字節(jié)碼翻譯為機(jī)器碼并執(zhí)行
? 特點(diǎn):一次編譯到處運(yùn)行——現(xiàn)在的JVM不僅可以執(zhí)行java字節(jié)碼,還可以執(zhí)行其他語(yǔ)言編譯后的字節(jié)碼文件,是一個(gè)跨語(yǔ)言平臺(tái)。自動(dòng)的內(nèi)存分配,自動(dòng)垃圾回收功能。
1.4JVM整體組成
1.類(lèi)加器(負(fù)責(zé)加載字節(jié)碼文件)
2.運(yùn)行時(shí)數(shù)據(jù)區(qū)(存儲(chǔ)運(yùn)時(shí)數(shù)據(jù),堆,java虛擬機(jī)棧(運(yùn)行java自己的方法),方法區(qū),程序計(jì)數(shù)器,本地方法棧)
3.執(zhí)行引擎(更底層,把字節(jié)碼翻譯為機(jī)器碼)
4.本地方法接口
程序在執(zhí)行之前要先把java代碼轉(zhuǎn)換成字節(jié)碼(class文件),jvm首先需要把字節(jié)碼通過(guò)類(lèi)加載器,把文件加載到內(nèi)存中的運(yùn)行時(shí)數(shù)據(jù)區(qū)。字節(jié)碼并不能由底層系統(tǒng)直接執(zhí)行,需要執(zhí)行引擎將字節(jié)碼文件翻譯成底層系統(tǒng)指令交由cpu去執(zhí)行,在這個(gè)過(guò)程中需要調(diào)用其他語(yǔ)言的本地方法接口來(lái)實(shí)現(xiàn)整個(gè)程序的功能。
2.JVM結(jié)構(gòu)-類(lèi)加載
2.1類(lèi)加載器子系統(tǒng)

?2.2類(lèi)加載過(guò)程
??????? 使用IO讀取字節(jié)碼文件,轉(zhuǎn)換并存儲(chǔ), 為每個(gè)類(lèi)創(chuàng)建一個(gè)Class類(lèi)的對(duì)象,存儲(chǔ)在方法區(qū)中
鏈接(驗(yàn)證,準(zhǔn)備,解析)
?????? 驗(yàn)證: 對(duì)字節(jié)碼文件格式進(jìn)行驗(yàn)證,文件是否被污染,對(duì)基本的語(yǔ)法格式進(jìn)行驗(yàn)證。
???? ? 準(zhǔn)備: 為靜態(tài)的變量進(jìn)行內(nèi)存分配。
public static int value = 123;value 在準(zhǔn)備階段后的初始值是 0,而不是 123
靜態(tài)常量(final修飾)在編譯期間就初始化。
解析: 將符號(hào)引用轉(zhuǎn)為直接引用,將字節(jié)碼中的表現(xiàn)形式,轉(zhuǎn)為內(nèi)存中表現(xiàn)(內(nèi)存地址)。
初始化: 類(lèi)的初始化,為類(lèi)中的定義的靜態(tài)變量進(jìn)行賦值。
public static int value = 123;value 在初始化階段后值是 123.
類(lèi)什么時(shí)候會(huì)被加載
1.在類(lèi)中運(yùn)行main方法
2.創(chuàng)建對(duì)象
3.使用類(lèi)中的靜態(tài)變量,靜態(tài)方法
4.反射 Class.forName("類(lèi)的地址");
5.子類(lèi)被加載
以下兩種情況類(lèi)不會(huì)被初始化:
static final int b = 20; 編譯期間賦值的靜態(tài)常量
System.out.println(User.b);
User[] users = new User[10];? 作為數(shù)組類(lèi)型
2.3類(lèi)加載器
具體的負(fù)責(zé)加載類(lèi)的一些代碼
1.引導(dǎo)類(lèi)加載器:用c/c++語(yǔ)言開(kāi)發(fā)的, jvm底層的開(kāi)發(fā)語(yǔ)言,負(fù)責(zé)加載java核心類(lèi)庫(kù),與java語(yǔ)言無(wú)關(guān)的。
2.擴(kuò)展類(lèi)加載器:java 語(yǔ)言編寫(xiě)的,由 sun.misc.Launcher$ExtClassLoader 實(shí)現(xiàn),繼承ClassLoader類(lèi)。從 JDK 系統(tǒng)安裝目錄的 jre/lib/ext 子目錄(擴(kuò)展目錄)下加載類(lèi)庫(kù)。
3.應(yīng)用程序類(lèi)加載器:Java 語(yǔ)言編寫(xiě)的,由 sun.misc.Launcher$AppClassLoader 實(shí)現(xiàn). 派生于 ClassLoader 類(lèi)。加載程序中自己開(kāi)發(fā)的類(lèi)。
4.自定義類(lèi)加載器
雙親委派機(jī)制
????? 為了保證程序的安全,防止自己寫(xiě)的類(lèi)替換核心類(lèi), java使用按需加載,當(dāng)需要加載一個(gè)類(lèi)時(shí),先委托給父類(lèi)加載器加載,如果父加載器沒(méi)有找到,繼續(xù)向上級(jí)委托,直到引導(dǎo)類(lèi)加載器。父級(jí)找到就返回,父級(jí)如果最終沒(méi)有找到,拋出ClassNotFoundException,向下委派給子級(jí)加載器,找到返回該類(lèi),最終沒(méi)有找到,報(bào)ClassNotFoundException。這是因?yàn)橐却_保加載系統(tǒng)類(lèi)。
?
雙親委派機(jī)制,是java提供的類(lèi)加載的規(guī)范,但不是強(qiáng)制不能改變的。
我們可以通過(guò)自定義的類(lèi)加載器,改變加載方式.
打破雙親委派機(jī)制
??????? 可以通過(guò)繼承ClassLoader類(lèi),重寫(xiě)loadClass(實(shí)現(xiàn)雙親委派的地方,不推薦)/findClass(推薦)方法,實(shí)現(xiàn)自定義的類(lèi)加載。
典型的tomcat中,加載部署在tomcat中的項(xiàng)目時(shí),就使用的是自己的類(lèi)加載器