參考鏈接:
JVM之內存結構詳解
https://www.choupangxia.com/2019/10/18/jvm%E4%B9%8B%E5%86%85%E5%AD%98%E7%BB%93%E6%9E%84%E8%AF%A6%E8%A7%A3/
緒論
1.什麼是Java虛擬機?
Java虛擬機是一個可以執行Java字節碼的虛擬機進程。Java源文件被編譯成能被Java虛擬機執行的字節碼文件。
2.爲什麼Java被稱作是“平臺無關的編程語言”?
一般的高級語言如要在不同的平臺上運行,至少需要編譯成不同的目標代碼。Java虛擬機讓這個變爲可能,因爲它知道底層硬件平臺的指令長度和其他特性。而引入JVM後,Java語言在不同平臺上運行時不需要重新編譯。Java語言使用模式Java虛擬機屏蔽了與具體平臺相關的信息,使得Java語言編譯程序只需生成在Java虛擬機上運行的目標代碼(字節碼),就可以在多種平臺上不加修改地運行。Java虛擬機在執行字節碼時,把字節碼解釋成具體平臺上的機器指令執行。
3.jvm最大內存限制多少?
默認是物理內存的1/64,JVM最大分配的內存由-Xmx指定,默認是物理內存的1/4。
一、Java 類加載過程?
類加載器就是尋找類或接口字節碼文件進行解析並構造JVM內部對象表示的組件。
在java中類裝載器把一個類裝入JVM,經過以下步驟:
- 加載:查找和加載Class文件。加載是類加載過程的一個階段,這兩個概念一定不要混淆。
- 鏈接:其中解析步驟是可以選擇的
(a)檢查:檢查載入的class文件數據的正確性
(b)準備:給類的靜態變量分配存儲空間
(c) 解析:將符號引用轉成直接引用 - 初始化:對靜態變量,靜態代碼塊執行初始化工作
類的加載過程
當Java程序需要使用某個類時,如果該類還未被加載到內存中,JVM會通過加載、連接(驗證、準備和解析)、初始化三個步驟來對該類進行初始化。當初始化一個類的時候, 如果發現其父類還沒有進行過初始化, 則需要先觸發其父類的初始化。
二、 描述一下 JVM 加載 Class 文件的原理機制?
類的加載:加載是類加載過程的一個階段,這兩個概念一定不要混淆。
在加載階段, 虛擬機需要完成以下三件事情:
- 1)通過一個類的全限定名來獲取定義此類的二進制字節流。
- 2)將這個字節流所代表的靜態存儲結構轉化爲方法區的運行時數據結構。
- 3)將類的class文件讀入內存,併爲之創建一個java.lang.Class對象,也就是說當程序中使用任何類時,系統都會爲之建立一java.lang.Class對象, 作爲方法區中這個類的各種數據的訪問入口。
三、什麼是類加載器,類加載器有哪些?
Java類加載器是Java運行時環境的一部分,負責動態加載Java類到Java虛擬機的內存空間中。
JVM中的類的加載器主要有三種:啓動類加載器,拓展類加載器,應用類加載器。
- 啓動類加載器(Bootstrap classLoader):又稱爲引導類加載器,由C++編寫,無法通過程序得到。主要負責加載JAVA中的一些核心類庫,主要是位於<JAVA_HOME>/lib/rt.jar中。
- 拓展類加載器(Extension classLoader):主要加載JAVA中的一些拓展類,位於<JAVA_HOME>/lib/ext中,是啓動類加載器的子類。
- 應用類加載器System classLoader:又稱爲系統類加載器,主要用於加載CLASSPATH路徑下我們自己寫的類,是拓展類加載器的子類。
四、類加載器雙親委派模型機制?
雙親委派模型過程:某個特定的類加載器在接到加載類的請求時,首先將加載任務委託給父類加載器,依次遞歸,如果父類加載器可以完成類加載任務,就成功返回;只有父類加載器無法完成此加載任務時,才自己去加載。
五、Java 內存分配?
先說說JVM內存結構,如圖
首先,JVM分爲五個區域:棧(虛擬機棧、本地方法棧)、堆、方法區、程序計數器。
1.程序計數器:
是一塊較小內存,可以看作是當前線程所執行的字節碼的行號指示器。
每條線程都需要有一個獨立的程序計數器,各個線程之間計數器互不影響。
通過改變計數器的值來選取下一條字節指令。
2.棧:
存放基本類型的數據和對象的引用,但對象本身不存放在棧中,而是存放在堆中。
Java虛擬機棧:
Java虛擬機棧也是線程私有,他的生命週期與線程相同。
虛擬機棧描述的是Java方法執行的內存模型:
每個方法在執行的同時都會創建一個棧幀用於存儲局部變量、操作數、操作數棧、動態鏈接、方法出口等信息。
每一個方法的調用過程直至執行完成的過程,就對應着一個棧幀在虛擬機棧中入棧到出棧的過程。
本地方法棧:
與虛擬機棧類似,
他們之間的區別是虛擬機棧爲虛擬機執行Java方法(字節碼)服務,
而本地方法棧則爲虛擬機使用到的Native方法服務。
3.堆:
堆內存用來存放由new創建的對象和數組。
Java堆是Java虛擬機所管理的內存中最大的一塊。
Java堆是垃圾收集器管理的主要區域。
Java堆是被所有線程共享的一塊內存區域。
4.方法區:
和Java堆一樣也是各個線程共享的內存區域,他用於存儲已被虛擬機加載的
類信息、常量、靜態變量、即時編譯後的代碼等數據。
下面說說對象運行過程中的內存分配(舉例):
- 程序從 main 方法中進入;運行到 People p 時,在棧中開闢了一個空間;
- new Phone() 時,在堆中開了一個內存空間,此時會有一個內存值爲 0x0001,p指向該地址;此時會找到對應的 People 的 class 文件,發現有三個變量和三個方法,於是將三個成員變量放在了堆中,但是此時的值爲默認值。注意,在方法區裏也有一個地址值,假設爲 0x001,可以認爲在堆中有一個方法區地址,通過在堆中的地址,可以找到方法區中相對應的方法;