JVM是Java Virtual Machine(Java虛擬機)的縮寫。
Java虛擬機主要分爲五大模塊:類裝載器子系統、運行時數據區、執行引擎、本地方法接口和垃圾收集模塊。
而爲主要的,經常被問起的,就只有類裝載器子系統、運行時數據區和垃圾收集模塊。
一.類裝載機制
這個要了解,類加載機制的具體流程,和流程都做了什麼。
類從被加載到虛擬機內存中開始,到卸載出內存爲止,它的整個生命週期包括:加載(Loading)、驗證(Verification)、準備(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸載(Unloading)7個階段。其中驗證、準備、解析3個部分統稱爲連接(Linking)。
a.加載:就是加載.class文件,這中間做了三件事,
1.通過類的全限定名獲取相應的二進制字節流。
2.將字節流代表的靜態存儲結構化爲方法區的運行時數據結構。
3.在內存中生成一個代表這個類的java.lang.Class對象,作爲方法區這個類的各種數據的訪問入口。
b.驗證
1.文件格式驗證,驗證class文件的版本號是否可處理
2.元數據驗證,驗證java語言規範
3.字節碼驗證
4.符號引用驗證
c.準備
準備階段是正式爲類變量分配內存並設置類變量初始值的階段,這些內存都將在方法區中進行分配。這時候進行內存分配的僅包括類變量(static 修飾的變量),而不包括實例變量,實例變量將會在對象實例化時隨着對象一起分配在java堆中。
準備階段的分配僅僅是分配內存空間,值還是默認的。例如
public static int num=1;
準備階段之後 num值0,準備階段只是分配空間。
d.解析
解析階段是虛擬機常量池內的符號引用替換爲直接引用的過程。
e.初始化
類的初始化階段是類加載過程的最後一步,在準備階段,類變量已賦過一次系統要求的初始值,而在初始化階段,則是根據程序員通過程序制定的主觀計劃去初始化類變量和其他資源。
二.運行時數據區(JVM內存區域)
分別爲堆,棧,元空間(1.7叫方法區/永久代)
a.堆(線程共享)
對象實例幾乎都在這,也是垃圾回收主要發生的地方。
堆的劃分:
1.新生代:(1/3)
Eden 區(初始對象在這,98%的對象需要回收),Survivor區(from,to兩塊);
eden : from:to默認比例8:1:1,from和to兩者同時只有一個有數據,
YongGC使用複製回收算法--eden 和Survivor from(有值的區域)存活數據複製到to(空的),存活一次,年齡+1,存活到15晉級老年代(或者某個年齡的數據量達到50%觸發提前晉級)
2.老年代(2/3)
數據來源:新生代數據晉級過來的(提前晉級或正常晉級);數據過大,直接分配在老年代
FullGC
虛擬機配置
-Xms256m 初始堆大小
-Xmx512m 堆最大
-Xmn80m 新生代大小
-Xss 每個線程大小(默認1M,基本不用管,夠用)
–XX:NewRatio=2 新生代與老年代的比例,老年代:新生代,新生代佔三分之一
-XX:SurvivorRatio=8 新生代Eden與Survivor from to 比例,eden:from:to 8:1:1
b.棧(線程獨享,內部是一個個的棧幀,每個棧幀都是一個方法)
劃分:
1.虛擬機棧,每個線程私有的,線程在運行時,在執行每個方法的時候都會打包成一個棧幀,存儲了局部變量表,操作數棧,動態鏈接,方法出口等信息,然後放入棧。每個時刻正在執行的當前方法就是虛擬機棧頂的棧楨。方法的執行就對應着棧幀在虛擬機棧中入棧和出棧的過程。
2.本地方法棧,本地方法
3.程序計數器 ,記錄程序運行到哪了,線程切換
c.元空間(1.8之後,之前是永久代)
用於存儲已經被虛擬機加載的類信息,常量("zdy","123"等),靜態變量(static變量)等數據,可用以下參數調整:
jdk1.7及以前:-XX:PermSize;-XX:MaxPermSize;
jdk1.8以後:-XX:MetaspaceSize; -XX:MaxMetaspaceSize