JVM基础知识1---尚硅谷视频笔记整理
JVM的知識
總體分為三個部分,從上到下,依次是:類加載器,運行時數(shù)據(jù)區(qū),執(zhí)行引擎和本地方法接口。其中最重要的部分是運行時數(shù)據(jù)區(qū),該區(qū)包括:方法區(qū),堆,java棧,本地方法棧,程序計數(shù)器。其整體架構如圖所示:
運行時數(shù)據(jù)區(qū)中暗色部分代表線程私有,占用內(nèi)存少;亮色部分則是可以被線程共享的,且存在垃圾回收。
2. 類加載器
掌握的三個要點:
(1) 有哪幾種類加載器
(2) 雙親委托機制
(3) 沙箱安全機制
作用:負責加載class文件,class文件在文件開頭有特定的文件標示,將class文件字節(jié)碼內(nèi)容加載到內(nèi)存中,并將這些內(nèi)容轉換成方法區(qū)中的運行時數(shù)據(jù)結構并且ClassLoader只負責class文件的加載,至于它是否可以運行,則由Execution Engine(執(zhí)行引擎)決定。
通俗解釋:ClassLoader就相當于快遞員,因此,可以有多種類加載器
λ 虛擬機自帶的加載器
λ 啟動類加載器(Bootstrap)C++
λ 擴展類加載器(Eextension)java
λ 應用程序類加載器(AppClass)
java也叫系統(tǒng)類加載器,加載前應用的classpath的所有類
λ 用戶自定義加載器
java.lang.ClassLoader的子類,用戶可以定制類的加載方式
public class MyObject {
public static void main(String[] args) {
//Object類是JDK自帶的類,加載它用的是Bootstrap啟動類加載器,但是該類是c++寫的,因此用getClassLoader()獲得的是null
Object object=new Object(); System.out.println(object.getClass().getClassLoader());
// MyObject類是自己定義的,使用的是AppClassLoader應用程序加載器
Object myobject=new MyObject(); System.out.println(myobject.getClass().getClassLoader());
}
}
運行結果:
null
jdk.internal.loader.ClassLoaders$AppClassLoader@3d4eac69
類加載器的繼承結構:
public class MyObject {
public static void main(String[] args) {
Object myobject=new MyObject(); System.out.println(myobject.getClass().getClassLoader().getParent().getParent()); System.out.println(myobject.getClass().getClassLoader().getParent()); System.out.println(myobject.getClass().getClassLoader());
}
}
運行結果:
//自定義類的父親的父親的加載器就是啟動類加載器
null
//自定義類的父親的加載器就是擴展類加載器
jdk.internal.loader.ClassLoadersPlatformClassLoader@38af3868//自定義類的加載器就是應用程序類加載器jdk.internal.loader.ClassLoadersPlatformClassLoader@38af3868 //自定義類的加載器就是應用程序類加載器 jdk.internal.loader.ClassLoadersPlatformClassLoader@38af3868//自定義類的加載器就是應用程序類加載器jdk.internal.loader.ClassLoadersAppClassLoader@3d4eac69
4 類加載器的雙親委托機制和沙箱安全機制
當一個類收到了類加載請求,它首先不會嘗試自己去加載這個類,而是把這個請求委派給父類去完成,每一個層次類加載器都是如此,因此所有的加載請求都應該傳送到啟動類加載器中,只有當父類加載器反饋自己無法完成這個請求的時候(再它的加載路徑下沒有找到所需加載的class),子類加載器才會嘗試自己去加載。
采用雙親委派的一個好處是比如加載位于rt.jar包中的類java.lang.Object,不管是哪個加載器加載這個類,最后都是委托給頂層的啟動類加載器進行加載,這樣就保證了使用不同的類加載最終得到的都是同樣一個Object對象。
5執(zhí)行引擎負責解釋命令,提交操作系統(tǒng)執(zhí)行
6 Native Interface本地接口
本地接口的作用是融合不同的編程語言為java所用。Java誕生的時候是c/c++橫行的時候,要想立足,必須有調(diào)用c/c++程序,于是就在內(nèi)存中專門開辟了一塊區(qū)域處理標記為native的代碼,它的具體做法是Native Method Stack中登記native方法,再Execution Engine執(zhí)行時加載native libraries.
Native Method Stack本地方法棧:
在Native Method Stack中登記native方法,在Execution Engine執(zhí)行時加載本地方法。
7 程序計數(shù)器
每個線程都有一個程序計數(shù)器,是線程私有的,就是一個指針,指向方法區(qū)中的方法字節(jié)碼(用來存儲指向下一條指令的地址,也就是即將要執(zhí)行的指定代碼),由執(zhí)行引擎讀取下一條指令,是一個非常小的內(nèi)存空間,幾乎可以忽略不計。
這塊內(nèi)存區(qū)域很小,它是當前線程所執(zhí)行的字節(jié)碼的行號指示器,字節(jié)碼解釋器通過改變這個計數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令。
如果執(zhí)行的是一個Native方法,那這個計數(shù)器是空的。
用以完成分支,循環(huán),跳轉,異常處理,線程回復等基礎功能。不會發(fā)生內(nèi)存溢出(OutOfMemory=OOM)錯誤。
通俗解釋:
PC寄存器記錄了方法之間的調(diào)用和執(zhí)行情況,類似排班值日表,用來存儲指向下一條指令的地址,也就是即將要執(zhí)行的指令代碼,它是當前線程所執(zhí)行的字節(jié)碼的行號指示器。
8 方法區(qū)
供各線程共享的運行時內(nèi)存區(qū)域,它存儲了每一個類的結構信息(模板),例如,運行時常量池(Runtime Constant Pool),字段和方法數(shù)據(jù),構造函數(shù)和普通方法的字節(jié)碼內(nèi)容。上面講的是規(guī)范,在不同的虛擬機里實現(xiàn)是不一樣的,最典型的就是永久代(PermGen space)和元空間。
空調(diào) k1=new 格力();
List list=new ArrayList();
方法區(qū) f =new 永久代;
方法區(qū) f =new 元空間;
但是,實例變量存在堆內(nèi)存中,和方法區(qū)無關。
文章內(nèi)容來自于尚硅谷視頻的筆記整理,如有侵權,聯(lián)系刪除
總結
以上是生活随笔為你收集整理的JVM基础知识1---尚硅谷视频笔记整理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学电脑编程能干什么
- 下一篇: Maven的下载安装和环境配置