Java虛擬機總結(jié)

JVM體系四大塊:

  • 類的加載
  • JVM內(nèi)存結(jié)構(gòu)
  • GC算法 垃圾回收
  • GC分析 性能調(diào)優(yōu)
  • 執(zhí)行引擎

JVM架構(gòu)圖


jvm.arch

一、類的加載機制

類的加載
類的加載,將class文件讀入方法區(qū),然后在堆中創(chuàng)建java.lang.Class對象。類的加載最終是生成堆區(qū)中的Class對象。Class對象封裝類在方法區(qū)中的數(shù)據(jù)結(jié)構(gòu),并提供訪問方法區(qū)中的數(shù)據(jù)結(jié)構(gòu)的接口。

類的生命周期
類的生命周期包括:加載、連接、初始化、使用和卸載,其中前三步是類的加載過程。

class.lifecycle
  • 加載,查找并加載類的二進制數(shù)據(jù),在Java堆中創(chuàng)建Class類的對象。
  • 鏈接,
    • 驗證,文件格式、元數(shù)據(jù)、字節(jié)碼、符號引用的驗證。
    • 準備,為類的靜態(tài)變量分配內(nèi)存,并初始化為默認值。
    • 解析,把類中的符號引用轉(zhuǎn)換為直接引用。
  • 初始化,為類的靜態(tài)變量賦予手動設(shè)置的初始值。
  • 使用,new出對象,在程序中使用。
  • 卸載,執(zhí)行垃圾回收。

幾個小問題

1、JVM初始化步驟 ? 2、類初始化時機 ?3、哪幾種情況下,Java虛擬機將結(jié)束生命周期?

答案參考 jvm系列(一):java類的加載機制

類加載器

啟動類加載器:Bootstrap ClassLoader擴展類加載器:Extension ClassLoader應(yīng)用程序類加載器:Application ClassLoader

類加載機制
全盤負責(zé),當一個類加載器負責(zé)加載某個Class時,該Class所依賴的和引用的其他Class也由該類加載器負責(zé)載入,除非顯示使用另外一個類加載器來載入。
父類委托,先讓父類加載器嘗試加載該類,只有在父類加載器無法加載時才從自己的類路徑中加載該類。
緩存機制,緩存機制保證所有加載過的Class都會被緩存。當程序中需要使用某個Class時,類加載器先從緩存區(qū)尋找該Class,只有緩存區(qū)中不存在,系統(tǒng)才會讀取該類對應(yīng)的二進制數(shù)據(jù),并將其轉(zhuǎn)換成Class對象存入緩存區(qū)。這就是為什么修改了Class后,必須重啟JVM,程序的修改才會生效。

二、JVM內(nèi)存結(jié)構(gòu)

jvm內(nèi)存結(jié)構(gòu)

  • Java堆(Heap),只存放對象實例,幾乎所有的對象實例都在這里。
  • 方法區(qū)(Method Area),存儲已被加載的類信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼。
  • 程序計數(shù)器(Program Counter Register),當前線程所執(zhí)行的字節(jié)碼的行號指示器。
  • JVM棧(JVM Stacks),其生命周期與線程相同。虛擬機棧描述的是Java方法執(zhí)行的內(nèi)存模型:方法被執(zhí)行的時候同時會創(chuàng)建一個棧幀(Stack Frame)用于存儲局部變量表、操作棧、動態(tài)鏈接、方法出口等信息。方法從被調(diào)用到執(zhí)行完成的過程,就對應(yīng)著棧幀在棧中從入棧到出棧的過程。
  • 本地方法棧(Native Method Stacks),與虛擬機棧類似,虛擬機棧為虛擬機執(zhí)行Java方法(字節(jié)碼)服務(wù),而本地方法棧為虛擬機使用到的Native方法服務(wù)。

對象分配規(guī)則

  • 對象優(yōu)先分配在Eden區(qū),如果Eden區(qū)沒有足夠空間時,執(zhí)行minor GC。
  • 大對象直接進入老年代。可以避免在eden區(qū)和兩個survivor區(qū)之間發(fā)生大量的內(nèi)存拷貝(新生代采用復(fù)制算法收集內(nèi)存)。
  • 長期存活的對象進入老年代。虛擬機為對象定義了一個年齡計數(shù)器,如果對象經(jīng)過了1次minor GC那么對象會進入survivor區(qū),之后每經(jīng)過一次minor GC那么對象的年齡加1,直到達到閥值,對象進入老年區(qū)。
  • 動態(tài)判斷對象的年齡。如果survivor區(qū)中相同年齡的所有對象大小的總和大于survivor空間的一半,年齡大于或等于該年齡的對象直接進入老年代。
  • 空間分配擔(dān)保。每次進行minor GC時,JVM計算survivor區(qū)移至老年區(qū)的對象的平均大小,如果這個值大于老年區(qū)的剩余值則進行一次full GC。如果小于檢查HandlePromotionFailure參數(shù)值,則只進行minor GC,否則進行Full GC。

三、GC算法 垃圾回收

1、對象存活判斷方式

  • 引用計數(shù):每個對象有一個引用計數(shù)屬性,新增一個引用時計數(shù)加1,引用釋放時減1,計數(shù)為0時可以回收。此方法簡單,但無法解決對象循環(huán)引用的問題。
  • 可達性分析:從GC roots向下搜索,搜索所走過的路徑稱為引用鏈。當對象到GC Roots沒有任何引用鏈相連時,則證明此對象是不可用的,不可達對象。
    GC roots包括:虛擬機棧中引用的對象。本地方法棧中JNI引用的對象。 方法區(qū)中類靜態(tài)屬性、常量引用的對象。

2、GC算法

  • 標記 -清除(Mark-Sweep)算法,分為“標記”和“清除”兩個階段:首先標記出所有需要回收的對象,在標記完成后回收所有被標記的對象。
  • 復(fù)制算法(Copying),將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當這一塊的內(nèi)存用完了,就將還存活的對象復(fù)制到另外一塊上,然后再把已使用過的內(nèi)存空間一次清理掉。
  • 標記-整理算法,標記過程與“標記-清除”算法一樣,但后續(xù)步驟是讓所有存活的對象向一端移動,然后清理掉端邊界以外的內(nèi)存。
  • 分代收集算法(Generational Collection),把堆分為新生代和老年代,根據(jù)各年代的特點采用適當?shù)氖占惴ā#?*常用
  • 分區(qū)

3、垃圾回收器

  • Serial回收器,是最古老,最穩(wěn)定以及效率高的收集器,可能會產(chǎn)生較長的停頓,只能用一個線程回收。
  • ParNew回收器,ParNew收集器是Serial收集器的多線程版本。
  • Parallel Scavenge回收器,類似ParNew收集器,Parallel收集器更關(guān)注系統(tǒng)的吞吐量
  • CMS(Concurrent Mark Sweep)收集器,以獲取最短回收停頓時間為目標的收集器。
  • G1(Garbage-First)收集器,是面向服務(wù)器的垃圾收集器,主要針對配備多顆處理器及大容量內(nèi)存的機器。以極高概率滿足GC停頓時間的同時,還具備高吞吐量。

三、GC分析 性能調(diào)優(yōu)

1、GC日志分析

[GC [<collector>: <starting occupancy1> -> <ending occupancy1>, <pause time1> secs] <starting occupancy3> -> <ending occupancy3>, <pause time3> secs] [Times: user=secs sys=secs, real=secs]

<collector>GC收集器的名稱
<starting occupancy1> 新生代在GC前占用的內(nèi)存
<ending occupancy1> 新生代在GC后占用的內(nèi)存
<pause time1> 新生代局部收集時jvm暫停處理的時間
<starting occupancy3> JVM Heap 在GC前占用的內(nèi)存
<ending occupancy3> JVM Heap 在GC后占用的內(nèi)存
<pause time3> GC過程中jvm暫停處理的總時間
<user>用戶時間
<sys>系統(tǒng)時間
<real>實際時間

4.231: [GC 4.231: [DefNew: 4928K->512K(4928K), 0.0044047 secs] 6835K->3468K(15872K), 0.0045291secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

4.445: [Full GC (System) 4.445: [Tenured: 2956K->3043K(10944K), 0.1869806 secs] 4034K->3043K(15872K), [Perm : 3400K->3400K(12288K)], 0.1870847secs] [Times: user=0.05 sys=0.00, real=0.19 secs]

最前面的數(shù)字 4.231 和 4.445 代表虛擬機啟動以來的秒數(shù)。
接下來的 [DefNew , [Tenured , [Perm 表示 GC 發(fā)生的區(qū)域,區(qū)域的名稱與使用的 GC 收集器相關(guān)。 Serial 收集器中新生代名為 "Default New Generation",顯示的名字為 "[DefNew"。ParNew收集器顯示的是 "[ParNew", “Parallel New Generation”。 Parallel Scavenge 收集器新生代名為 "PSYoungGen"。年老代和永久代名稱也都由收集器決定。
方括號內(nèi)部顯示的 “4928K->512K(4928K)” 表示 “GC 前該區(qū)域已使用容量 -> 垃圾回收后該區(qū)域已使用容量 (該區(qū)域內(nèi)存總?cè)萘? ”。
再往后的 “0.0044047 secs” 表示該區(qū)域GC所用時間,單位是秒。
再往后的 “6835K->3468K(15872K)” 表示 “GC 前Java堆已使用容量 -> GC后Java堆已使用容量 (Java堆總?cè)萘浚薄?br> 再往后的 “0.0045291 secs” 是Java堆GC所用的總時間。
最后的 “[Times: user=0.00 sys=0.00, real=0.00 secs]” 分別代表用戶態(tài)消耗的CPU時間、內(nèi)核態(tài)消耗的CPU時間和操作從開始到結(jié)束所經(jīng)過的墻鐘時間。
墻鐘時間包括各種非運算的等待耗時,如IO等待、線程阻塞。CPU時間不包括等待時間,當系統(tǒng)有多核時,多線程操作會疊加這些CPU時間,所以user或sys時間會超過real時間。

2、調(diào)優(yōu)命令

JDK監(jiān)控和故障處理命令

  • jps,顯示指定系統(tǒng)內(nèi)所有的HotSpot虛擬機進程。
  • jstat,用于監(jiān)視虛擬機運行時狀態(tài)信息,可以顯示出虛擬機進程中的類裝載、內(nèi)存、垃圾收集、JIT編譯等運行數(shù)據(jù)。
  • jmap,生成heap dump文件。
  • jhat,與jmap搭配使用,分析jmap生成的dump,jhat內(nèi)置了一個微型的HTTP/HTML服務(wù)器,生成dump的分析結(jié)果后,可以在瀏覽器中查看。
  • jstack,生成java虛擬機當前時刻的線程快照。
  • jinfo,實時查看和調(diào)整虛擬機運行參數(shù)。

3、調(diào)優(yōu)工具

常用調(diào)優(yōu)工具分為兩類,jdk自帶監(jiān)控工具:jconsole和jvisualvm;第三方有:MAT(Memory Analyzer Tool)。

  • jconsole,是從java5開始,JDK自帶的java監(jiān)控和管理控制臺,用于對JVM中內(nèi)存,線程和類等的監(jiān)控。
  • jvisualvm,jdk自帶全能工具,可以分析內(nèi)存快照、線程快照;監(jiān)控內(nèi)存變化、GC變化等。
  • MAT,Memory Analyzer Tool,基于Eclipse的內(nèi)存分析工具,是一個快速、功能豐富的Java heap分析工具,它可以幫助我們查找內(nèi)存泄漏和減少內(nèi)存消耗。

四、執(zhí)行引擎

分配給運行時數(shù)據(jù)區(qū)的字節(jié)碼將由執(zhí)行引擎執(zhí)行,執(zhí)行引擎讀取字節(jié)碼并逐個執(zhí)行。
(1) 解釋器:解釋器更快地解釋字節(jié)碼,但執(zhí)行緩慢。解釋器的缺點是當一個方法被調(diào)用多次時,每次都需要一個新的解釋。

(2) JIT編譯器:JIT編譯器消除了解釋器的缺點。執(zhí)行引擎將在轉(zhuǎn)換字節(jié)碼時使用解釋器的幫助,但是當它發(fā)現(xiàn)重復(fù)的代碼時,將使用JIT編譯器,編譯整個字節(jié)碼并將其更改為本地代碼。這個本地代碼將直接用于重復(fù)的方法調(diào)用,這提高了系統(tǒng)的性能。JIT的構(gòu)成組件為:

  • 中間代碼生成器(Intermediate Code Generator):生成中間代碼。
  • 代碼優(yōu)化器(Code Optimizer):優(yōu)化上面生成的中間代碼。
  • 目標代碼生成器(Target Code Generator):生成機器代碼或本地代碼。
  • 分析器(Profiler):查找熱點,即該方法是否被多次調(diào)用。

(3) 垃圾收集器(Garbage Collector):收集和刪除未引用的對象。可以通過調(diào)用“System.gc()”觸發(fā)垃圾收集,但不保證立即執(zhí)行。

Java本機接口(JNI):JNI與本機方法庫進行交互,并提供執(zhí)行引擎所需的本機庫。
本地方法庫(Native Method Libraries):它是執(zhí)行引擎所需的本機庫的集合。

參考

jvm系列(一):java類的加載機制
jvm系列(二):JVM內(nèi)存結(jié)構(gòu)
jvm系列(三):GC算法 垃圾收集器
jvm系列(四):jvm調(diào)優(yōu)-命令篇
jvm系列(七):jvm調(diào)優(yōu)-工具篇
http://www.ityouknow.com/
如何合理的規(guī)劃一次jvm性能調(diào)優(yōu)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,273評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,870評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,527評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,010評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,250評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,769評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,656評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,853評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,103評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,487評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,815評論 2 372

推薦閱讀更多精彩內(nèi)容