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後才進行壓縮。
老年代一般是由標記清除或者是標記清除與標記整理的混合實現