JVM虛擬機

繼續(xù)做知識點鋪墊求橄。

我這里再簡單梳理下虛擬機相關知識點今野,當然只是熱修復與插件化會涉及到的部分。

一罐农、JVM整體結構

java文件先通過編譯器生成虛擬機執(zhí)行的字節(jié)碼文件条霜,該文件被ClassLoader加載到內存,由虛擬機分區(qū)域進行內存管理涵亏,然后子系統(tǒng)會執(zhí)行相關的工作:包括將虛擬機字節(jié)碼編譯為機器碼宰睡、針對堆內存進行GC等等蒲凶。同時虛擬機通過本地庫接口連接native方法與本地方法庫。

1.1 編譯流程

class文件生成是通過javac編譯器程序執(zhí)行得到的拆内,整個編譯流程簡單總結如下:

源代碼->詞法分析器->Token流->語法分析器->語法樹/抽象語法樹->語義分析器->
注解抽象語法樹->字節(jié)碼生成器->jvm字節(jié)碼

這個部分就不管了旋圆,了解下點到為止,感興趣的可以自行研究麸恍。

1.2 類加載流程

類加載器介紹:
Bootstrap Loader 負責加載系統(tǒng)類灵巧;
Extension ClassLoader 負責加載擴展類(就是繼承類和現類);
System ClassLoader 負責加載用戶類或南。

(類加載器Andorid有比較大的區(qū)別孩等,但是思想還是一樣的)

這里牽涉到幾個機制:

  • 全盤負責:當一個類加載器負責加載某個Class時,該Class所依賴的和引用的其他Class也將由該類加載器負責載入采够,除非顯示使用另外一個類加載器來載入肄方。

  • 雙親委派:先判斷當前類加載器是否加載過,如果沒有則傳遞到父類類加載器中蹬癌,父類加載器沒有搜到該Class無法完成該加載权她,子加載器才會嘗試自己去加載該Class。

  • 緩存機制:緩存機制將會保證所有加載過的Class都會被緩存逝薪,當程序中需要使用某個Class時隅要,類加載器先從緩存區(qū)尋找該Class,只有緩存區(qū)不存在董济,系統(tǒng)才會讀取該類對應的二進制數據步清,并將其轉換成Class對象,存入緩存區(qū)虏肾。

如何判斷加載的是同一個類:類名相同廓啊、包名相同、由相同的ClassLoader加載封豪。

類加載的過程:

image.png
  • Loading:類的信息從文件中獲取并加載到JVM內存中谴轮。
  • Verifying:檢查讀入的結構是否符合JVM規(guī)范。
  • Preparing:驗證完正確吹埠,會分配一個結構來存儲類信息第步。
  • Resolving: 把這個類的常量池中的所有符號引用轉變?yōu)橹苯右谩?/li>
  • Initializing:執(zhí)行靜態(tài)初始化程序,把靜態(tài)變量初始化成指定的值缘琅。
1.3 內存管理
1.3.1 內存區(qū)域劃分
  • 程序計數器:一個指針粘都,記錄當前線程所執(zhí)行到的字節(jié)碼行號;
  • 虛擬機棧:存放方法執(zhí)行時的所有數據胯杭;
  • 本地方法棧:專門為native方法服務的驯杜;
  • 方法區(qū):存儲被虛擬機加載的類信息、常量做个、靜態(tài)變量鸽心、及時編譯器編譯后等數據;
  • java堆: 所有new創(chuàng)建的對象的內存都在堆中分配居暖。是虛擬機中最大的一塊內存顽频,是GC要回收的部分。

線程共享區(qū)包括:方法區(qū) 太闺、java堆糯景。
線程隔離區(qū)包括:虛擬機棧、本地方法棧省骂、程序計數器蟀淮。

1.3.2 虛擬機棧解析

以線程為單位由棧結構來進行管理。棧中對應的棧元素叫棧幀钞澳,它是用于支持虛擬機進行方法調用和方法執(zhí)行的數據結構怠惶,每個方法從調用到執(zhí)行完成就對應一個棧幀在虛擬機棧中入棧到出棧的過程。棧幀包含的內容:局部變量表轧粟、棧操作數策治、動態(tài)鏈接、方法出口兰吟。

1.3.3 java堆區(qū)解析

java堆是 JVM 所管理的最大的一塊內存空間通惫,主要用于存放各種類的實例對象。

在 Java 中混蔼,堆被劃分成兩個不同的區(qū)域:新生代 ( Young )履腋、老年代 ( Old )。新生代 ( Young ) 又被劃分為三個區(qū)域:Eden惭嚣、From Survivor遵湖、To Survivor。

簡單看下區(qū)域的劃分以及虛擬機默認分配的比例:

另外還有個永久代料按,這部分屬于方法區(qū)奄侠,就捎帶提一嘴。

那么载矿,這個比例可以配置嗎垄潮?當然可以,如果玩java服務器的話闷盔,肯定要玩玄學調參弯洗。參考如下JVM參數選項:

參數名 介紹
-Xms 初始堆大小。如:-Xms256m
-Xmx 最大堆大小逢勾。如:-Xmx512m
-Xmn 新生代大小牡整。通常為 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 個 Survivor 空間溺拱。實際可用空間為 = Eden + 1 個 Survivor逃贝,即 90%
-Xss JDK1.5+ 每個線程堆棧大小為 1M谣辞,一般來說如果棧不是很深的話, 1M 是絕對夠用了的沐扳。
-XX:NewRatio 新生代與老年代的比例泥从,如 –XX:NewRatio=2,則新生代占整個堆空間的1/3沪摄,老年代占2/3
-XX:SurvivorRatio 新生代中 Eden 與 Survivor 的比值躯嫉。默認值為 8。即 Eden 占新生代空間的 8/10杨拐,另外兩個 Survivor 各占 1/10
-XX:PermSize 永久代(方法區(qū))的初始大小
-XX:MaxPermSize 永久代(方法區(qū))的最大值
-XX:+PrintGCDetails 打印 GC 信息
-XX:+HeapDumpOnOutOfMemoryError 讓虛擬機在發(fā)生內存溢出時 Dump 出當前的內存堆轉儲快照祈餐,以便分析用

jvm 可配置的參數選項可以參考 Oracle 官方網站給出的相關信息:http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

堆內存管理規(guī)則:

新生代
新創(chuàng)建的對象先被放在Eden,Eden滿了哄陶,執(zhí)行Minor GC帆阳,同時把未被 GC 的對象 移動到 S0(from) 或 S1(to) 中。 最后使 S0(from) 奕筐、S1(to) 其中一個置為空舱痘,這是由GC算法決定的,因為Minor GC對應的是復制算法离赫,因此需要內存交換區(qū)芭逝,所以多分了from和to這兩塊區(qū)域。

老年代
內存區(qū)存放了經過多次 Minor GC 后仍然不能被 GC 的對象渊胸。Old區(qū)滿了旬盯,執(zhí)行Major GC。

另外要補充一點的是:新生代和新生代都可以主動觸發(fā) stop-the-world 事件翎猛,掛起所有任務胖翰,執(zhí)行 GC 操作。 被掛起的任務只有在 GC 執(zhí)行完畢后切厘,才會恢復執(zhí)行萨咳。

1.3.4 垃圾回收
垃圾收集算法:
  • 引用計算算法(jdk1.2之前):堆中的每個對象對應一個引用計數器,創(chuàng)建對象置為1疫稿,每次引用到此對象+1培他,其中一個引用銷毀-1,變?yōu)?即滿足回收遗座。致命缺點:循環(huán)引用的對象無法進行回收舀凛。

  • 可達性算法(jdk1.2之后):確定GC root,尋找路徑可達的引用節(jié)點途蒋,形成可達性樹猛遍,不在樹上的節(jié)點即滿足回收條件。
    在Java語言里,可作為GC Roots對象的包括如下幾種:

    • 虛擬機棧(棧楨中的本地變量表)中的引用的對象懊烤;
    • 方法區(qū)中的類靜態(tài)屬性引用的對象梯醒;
    • 方法區(qū)中的常量引用的對象;
    • 本地方法棧中JNI的引用的對象奸晴;
引用類型:
  • 強引用(StrongReference):JVM 寧可拋出 OOM 冤馏,也不會GC日麸;
  • 軟引用(SoftReference):只有在內存空間不足時寄啼,才會被回收;
  • 弱引用(WeakReference):在 GC 時代箭,一旦發(fā)現了只具有弱引用的對象墩划,不管當前內存空間足夠與否,都會回收它的內存嗡综;
  • 虛引用(PhantomReference):主要用來判斷對象是否將要被回收乙帮,屬于GC回收標志。
垃圾回收算法:

標記-清除算法(Tracing Collector):遍歷所有的GC Roots极景,然后將所有GC Roots可達的對象標記為存活的對象察净。對沒標記的對象全部清除。
優(yōu)點:對不存活對象進行處理盼樟,在存活對象高的情況下非常高效氢卡。
缺點:清除對象不會整理,造成內存碎片晨缴,這部分內存碎片屬于內部碎片译秦。

復制算法(Coping Collector): 遍歷所有的GC Roots,將可達的對象復制到另一塊內存空間,遍歷完后清空原來的內存空間(剩下的都是不可達對象)击碗。
優(yōu)點:對可達對象進行復制筑悴,在存活的對象比較少時極為高效。
缺點:需要額外的內存空間稍途。

標記-整理算法(Compacting Collector):在標記-清除算法基礎上阁吝,增加存活對象內存整理。
優(yōu)點:不造成內存碎片械拍,也不需要額外內存空間
缺點:整理過程耗時突勇,效率不高。

因此內前面咱們提到的兩個GC:
Minor GC: 是發(fā)生在新生代中的垃圾收集動作殊者,通常對象存活時間較短与境,因此采用的是復制算法。
Full GC: 是發(fā)生在老年代的垃圾收集動作猖吴,通常對象存活時間較長摔刁,因此采用的是標記-清除算法(考慮執(zhí)行效率)/標記-整理算法(考慮內存利用率)。

GC觸發(fā)時機:

  • Java虛擬機無法再為新的對象分配內存空間了海蔽;
  • 手動調用System.gc()方法(強烈不推薦:即使手動調了也不會立馬回收共屈,還會加大虛擬機壓力)绑谣;
  • 低優(yōu)先級的GC線程,被調度時拗引。

二借宵、JVM與DVM不同

  • 執(zhí)行文件不同,JVM對應class矾削,DVM對應dex壤玫。dex文件更精簡。
  • 虛擬機架構不同哼凯,JVM基于棧欲间,DVM基于寄存器。寄存器比是內存更快的存儲介質断部,因此DVM運行更快猎贴。
  • 類加載系統(tǒng)區(qū)別,JVM基于Bootstrap Loader蝴光、Extension ClassLoader她渴、App ClassLoader,DVM基于ClassLoader蔑祟、BaseDexClassLoader趁耗、PathClassLoader、DexClassLoader做瞪。
  • 項目中虛擬機數目不同对粪,JVM只能同時存在1個,DVM存在多個一個進程對應一個装蓬。

三著拭、ART與DVM相比較的優(yōu)勢

編譯優(yōu)化

DVM使用JIT來將字節(jié)碼編譯為機器碼,ART引入AOT預編譯牍帚。JIT生成的機器碼緩存在內存中儡遮,優(yōu)化解釋模式的執(zhí)行,屬于運行時優(yōu)化暗赶。而OAT生成的機器碼緩存為文件鄙币,屬于持久化優(yōu)化,因此下次執(zhí)行肯定是AOT的方式更快蹂随,不用重新生成機器碼十嘿,直接拿來用。

但是OAT的缺點是每次編譯dex2oat CPU占用率非常高岳锁,可能造成部分任務搶占不到CPU绩衷。另外ART安裝時間更長,存儲空間占用更大。

垃圾回收優(yōu)化

改善了Dalvik GC流程咳燕,將其非并發(fā)過程改變成了部分并發(fā)勿决。縮短了任務掛起時間招盲,據官方測試數據說gc效率提高2倍低缩。

內存優(yōu)化

ART對比DVM 提高了內存使用率,減少了內存碎片化曹货。

之前寫的相關文章:
虛擬機(一)-JVM執(zhí)行java代碼流程淺析
虛擬機(二)-Dalvik執(zhí)行java代碼流程淺析
虛擬機(三)-JVM 咆繁、DVM 、ART簡單對比
虛擬機(四)-JVM垃圾回收

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
禁止轉載控乾,如需轉載請通過簡信或評論聯系作者么介。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蜕衡,隨后出現的幾起案子,更是在濱河造成了極大的恐慌设拟,老刑警劉巖慨仿,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異纳胧,居然都是意外死亡镰吆,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門跑慕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來万皿,“玉大人,你說我怎么就攤上這事核行±喂瑁” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵芝雪,是天一觀的道長减余。 經常有香客問我,道長惩系,這世上最難降的妖魔是什么位岔? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮堡牡,結果婚禮上抒抬,老公的妹妹穿的比我還像新娘。我一直安慰自己晤柄,他們只是感情好擦剑,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般抓于。 火紅的嫁衣襯著肌膚如雪做粤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天捉撮,我揣著相機與錄音怕品,去河邊找鬼。 笑死巾遭,一個胖子當著我的面吹牛肉康,可吹牛的內容都是我干的。 我是一名探鬼主播灼舍,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼吼和,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了骑素?” 一聲冷哼從身側響起炫乓,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎献丑,沒想到半個月后末捣,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡创橄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年箩做,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妥畏。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡邦邦,死狀恐怖,靈堂內的尸體忽然破棺而出醉蚁,到底是詐尸還是另有隱情燃辖,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布馍管,位于F島的核電站郭赐,受9級特大地震影響,放射性物質發(fā)生泄漏确沸。R本人自食惡果不足惜捌锭,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望罗捎。 院中可真熱鬧观谦,春花似錦、人聲如沸桨菜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至泻红,卻和暖如春夭禽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谊路。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工讹躯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缠劝。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓潮梯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親惨恭。 傳聞我的和親對象是個殘疾皇子秉馏,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內容