jvm知識點總結
1 jvm結構圖
2 類的裝載器
將類的位元組碼文件載入到jvm中,會把這些內容轉化為方法區運行的數據結構。jvm會創建對應的Class對象,保存到堆中。
裝載器有如下幾種:虛擬機自帶裝載器:啟動類載入器(BootStrap)C++、擴展類載入器(Extension)Java、應用程式類載入器(AppClassLoader)Java,也叫系統類載入器,載入當前應用的classpath的所有類
用戶自定義載入器:Java.lang.ClassLoader的子類
雙親委派機制:如果一個類收到載入的請求,他首先會讓它的父類嘗試去完成,當他的父類無法完成時,它才會嘗試載入這個類。
沙箱:比如啟動類載入器它載入了java.lang.String,如果本地也是創建相同的包且有String類,它會以啟動的時候首先載入的那個類為準。
3 執行引擎
功能:解釋命令,提交給作業系統執行。
4 本地方法棧、本地方法介面、本地方法庫
native修飾的方法是本地方法,由於java程式碼無能為力,可能需要調用作業系統或C++等程式碼。這些方法會註冊到本地方法棧,這些本地方法通過調用本地方法介面調用非java程式碼,執行引擎會載入本地方法庫。
5 PC暫存器
用於指向當前執行緒所執行的位元組碼的行號顯示器
6 方法區
存儲類的結構資訊,有靜態變數(靜態域),運行時常量池、欄位和方法數據、構造函數和普通方法的位元組碼內容。在jdk7中這裡是永久代,jdk8採用的是元空間實現。
7 棧
在執行緒創建時創建,執行緒結束棧記憶體也結束,所有不存在垃圾回收。棧中存儲8種基本數據變數、對象的引用變數、實例方法。棧中存儲的方法就是棧幀,存儲三種數據,本地變數:輸入輸出參數以及方法內的變數,棧的操作:記錄入棧和出棧、棧幀數據:方法。
棧中存儲直接對象的地址,堆中存儲對象以及類元數據的地址即Class的地址,方法區存儲類元數據。
8 堆
在jdk7中堆在邏輯上分為新生區,養老區,永久存儲區,而在物理上堆只有新生區和養老區,永久存儲區為方法區,在jdk8中永久區被原空間取代,二者區別時永久存儲區使用堆記憶體,而元空間的大小和物理記憶體有關。
在伊甸區如果對象滿了,會觸發 Minor GC ,會把存活的對象移動到倖存0區(from),對象的年齡加一。第二次伊甸區對象滿了,會把倖存0區和伊甸區存活的對象複製到倖存1區並且年齡加一,倖存0區有from區變為to區,倖存1區由to變為from區,清理伊甸區和to區,這樣一直進行下去,如果哪些對象年齡達到15,就會進入養老區,這個值也可以自己設置,在jdk8種在0-15之間。如果養老區滿了,會觸發full gc。
9 GC演算法
分代收集演算法,新生區和養老區採用的演算法是不一樣的,由於新生區發生gc比較頻繁,而養老區次數比較少,在jdk7中永久存儲區基本不清理,在jdk8中元空間不使用堆記憶體故不需要清理。
9.1 引用計數法
在每次引用時,會加一,置為null會減一,但是這個演算法有如下缺點,要使用計數器,會有記憶體消耗,無法處理循環引用。
9.2 複製演算法
觸發 Minor GC ,會把存活的對象移動到倖存0區(from),對象的年齡加一。第二次伊甸區對象滿了,會把倖存0區和伊甸區存活的對象複製到倖存1區並且年齡加一,倖存0區有from區變為to區,倖存1區由to變為from區,清理伊甸區和to區,這樣一直進行下去,如果哪些對象年齡達到15,就會進入養老區。
缺點:①:消耗記憶體
②:如果生存率高的化,也是比較浪費的。
這個演算法在新生區使用,因為新生區存活率低。
9.3 標記清除
①:從根集合開始掃描,對存活的對象進行標記
②:掃描整個記憶體空間,清理未被標記的對象。
缺點:需要暫停整個應用,會產生記憶體碎片
老年代一般是由標記清除或者是標記清除與標記整理的混合實現
9.4 標記壓縮
①:從根集合開始掃描,對存活的對象進行標記
②:將標記的對象移動到一邊,不需要清理
缺點:雖然不需要回收對象,但是不僅要標記所有存活對象,還要整理所有存活對象的引用地址。
還有一個演算法是標記清除壓縮演算法,這個演算法結合3,4,和標記清除是類似的,只不過多次gc後才進行壓縮。
老年代一般是由標記清除或者是標記清除與標記整理的混合實現