Java Jvm(一):Jvm 與 GC 詳解

Jvm 虛擬機概念

  • Java 虛擬機(Jvm)是可運行 Java 代碼的假想計算機性宏,Java 虛擬機包括了一套字節(jié)碼指令集、一組寄存器(用于存儲每個線程下一條執(zhí)行的 Jvm 指令)蛇摸、一個棧好港、一個垃圾收集器和一個存儲方法域
  • 每一個平臺(操作系統(tǒng))的代碼解釋器是不同的鸽嫂,但是實現(xiàn)的虛擬機(Java虛擬機接口)是相同的,這也就是為什么 Java 能夠跨平臺

Java 代碼編譯和執(zhí)行過程

  • Java 源文件通過 Java 源碼編譯器生存相應(yīng)的 .class 文件(字節(jié)碼文件)
  • 而字節(jié)碼通過 Jvm 中的解釋器(字節(jié)碼指令集)編譯成特定的機器碼

Jvm 生命周期

  • Jvm 實例對應(yīng)了一個獨立運行的 Java 程序
  • 啟動一個 Java 程序時髓窜,一個 Jvm 實例就產(chǎn)生了扇苞,main() 函數(shù)作為 Jvm 實例運行的起點
  • Jvm 內(nèi)部有兩種線程:守護線程和非守護線程,main()屬于非守護線程寄纵,守護線程通常由 Jvm 自己使用鳖敷,Java 程序也可以聲明守護線程
  • 當程序中的所有非守護線程都終止時,Jvm 才退出程拭,若安全管理器允許定踱,程序也可以使用 Runtime 類或者 System.exit() 退出

Jvm 內(nèi)存組成

  • 所有通過 new 創(chuàng)建的對象的內(nèi)存都在堆中分配,堆的大小可以通過 -Xmx 和 -Xms 來控制
  • 堆內(nèi)存分為 3 部分:
    • 新生代(新生代進一步劃分為 Eden恃鞋、Survivor0崖媚、Survivor1 三個區(qū)):new 出來的對象一般情況下都會在新生代里的 Eden 區(qū)里面分配空間,如果存活時間足夠長則會進入 Survivor 區(qū)
    • 老年代:若新生代的對象存活更長則會被分配到老年代里
    • 永久代:存放的是 Class 類元數(shù)據(jù)恤浪、方法等

  • 每個線程執(zhí)行每個方法的時候都會在棧中申請一個棾┭疲空間
  • 每個棧空間包括局部變量區(qū)和操作數(shù)棧水由,用于存放此次方法調(diào)用過程中的臨時變量荠呐、參數(shù)和中間結(jié)果

本地方法棧

  • 用于支持 native 方法的執(zhí)行,存儲了每個 native 方法調(diào)用的狀態(tài)

方法區(qū)

  • 方法區(qū)域存放了所有加載的類信息(名稱、修飾符等)、類中的靜態(tài)變量芯肤、常量贪薪、類的方法信息等
  • 當開發(fā)人員通過 Class 對象中的 getName 等方法獲取信息時,這些數(shù)據(jù)都來源于方法區(qū)域昧互,同時方法區(qū)域也是全局共享的
Jvm 組成

GC 垃圾回收

  • Java 之所以不用像 C++ 一樣手動處理內(nèi)存的回收,是因為 JVM 虛擬機上增加了垃圾回收(GC)機制,GC 會在合適的時間觸發(fā)垃圾回收筝野,將不需要的內(nèi)存空間回收釋放,避免內(nèi)存增長導(dǎo)致 OOM(內(nèi)存泄露)
  • GC 會判斷對象是否存活確定是否回收粤剧,判斷對象是否存活一般有兩種方式:
    • 引用計數(shù):每一個對象都有一個引用計數(shù)屬性歇竟,新增一個引用時計數(shù)加 1,引用釋放時減 1抵恋,計數(shù)為 0 時可以回收焕议。此方法簡單,但無法解決對象相互循環(huán)引用問題
    • 可達性分析
      • 從 GC Roots 開始向下搜索弧关,搜索所走過的路徑稱為引用鏈盅安,當一個對象到 GC Roots 沒有任何引用鏈時唤锉,則證明此對象時不可用的,不可達對象
      • 在現(xiàn)實情況我們往往需要通過把指向某個對象的 Reference 置空來保證這個對象在下次 GB 運行的時候被回收
      Object c = new Car();
      c=null;
      
      • 可手動置空是一個很繁瑣的事情别瞭,對于簡單狀況窿祥,手動置空是不需要程序員來做的,因為對于簡單對象蝙寨,當調(diào)用它的方法執(zhí)行完畢之后晒衩,所指向它的引用會被 stack(棧)中 popup(出棧),所以它就能在下一次 GB 執(zhí)行時被回收了

垃圾收集算法

“標記-清除”

  • “標記-清除”算法墙歪,算法分為“標記”和“清除”兩個階段:
    • 首先標記出所有需要回收的對象
    • 在標記完成后統(tǒng)一回收掉所有被標記的對象
  • 之所以說它是最基礎(chǔ)的收集算法听系,是因為后續(xù)算法都是基于這種思路對其改進
  • 它的缺點主要是:
    • 效率問題:通過標記和清除過程效率都不高
    • 空間問題:標記清除后會產(chǎn)生大量不連續(xù)的內(nèi)存碎片,導(dǎo)致程序在以后的運行過程中需要分配較大內(nèi)存對象時無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動作

“復(fù)制”

  • “復(fù)制”算法將可用內(nèi)存按容量劃分為大小相等的兩塊虹菲,每次只使用其中一塊靠胜,當這一塊的內(nèi)存用完了,就將還存活的對象復(fù)制到另外一塊上面毕源,然后再把已使用過的內(nèi)存空間一次性清理掉
  • 這樣使得每次都是對其中一塊內(nèi)存進行回收浪漠,內(nèi)存分配時也就不用考慮內(nèi)存碎片等復(fù)雜情況,只要移動堆頂指針脑豹,按順序分配內(nèi)存即可郑藏,實現(xiàn)簡單,運行高效瘩欺。但這種算法代價是將內(nèi)存縮小為原來的一半

“標記-壓縮”

  • “復(fù)制”收集算法在對象存活率較高時就要執(zhí)行較多的復(fù)制操作必盖,效率將會變低,更關(guān)鍵的是俱饿,如果不想浪費 50% 的空間歌粥,就需要額外的空間提供分配擔保,以應(yīng)對被使用的內(nèi)存中所有對象都 100% 存活的極端情況拍埠,所以一般不能直接用這種算法
  • “標記-壓縮”標記過程與“標記-清除”算法一樣失驶,但后續(xù)步驟不是直接對可回收對象進行清理,而是讓所有存活對象都向一端移動枣购,然后直接清理掉端邊界以外的內(nèi)存

分代回收算法

  • “分代收集”算法把 Java 堆分成新生代和老年代嬉探,這樣就可以根據(jù)各個年代的特點采用最適當?shù)氖占惴?/li>
  • 在新生代中,每次垃圾收集時都發(fā)現(xiàn)有大批對象死去棉圈,只有少量的存活涩堤,主要采用復(fù)制算法,只需要付出少量存活對象的復(fù)制成本就可以完成收集
  • 而老年代中因為對象存活率較高分瘾、沒有額外空間對它進行分配擔保胎围,通常采用“標記-清除”或者“標記-壓縮”算法

GC 收集器

Serial 串行收集器

  • 串行收集器是最古老,最穩(wěn)定以及效率最高的收集器,可能會產(chǎn)生較長的停頓
  • 只使用一個線程去回收白魂,采用分代回收算法
  • 垃圾收集過程中會 Stop The World(服務(wù)暫停)

ParNew 并行收集器

  • ParNew 收集器其實就是 Serial 收集器的多線程版本

Parallel 收集器

  • Parallel 收集器類似 ParNew 收集器汽纤,Parallel 更關(guān)注系統(tǒng)的吞吐量,可以通過參數(shù)來打開自適應(yīng)調(diào)節(jié)策略
  • 虛擬機會根據(jù)當前系統(tǒng)運行情況收集性能監(jiān)控信息福荸,動態(tài)調(diào)整這些參數(shù)以提供最適合停頓時間或最大的吞吐量
  • 也可以通過參數(shù)控制 GC 時間大于多少毫秒或者比例

CMS 收集器

  • CMS 收集器是一種獲取最短回收停頓時間為目標的收集器
  • 目前很大一部分 Java 應(yīng)用是B/S 系統(tǒng)的服務(wù)端上蕴坪,這類應(yīng)用尤其重視服務(wù)器的響應(yīng)速度
  • CMS 基于 “標記-清除” 算法實現(xiàn),它的運作過程相對復(fù)雜敬锐,分為:
    • 初始標記
    • 并發(fā)標記
    • 重新標記
    • 并發(fā)清除
  • 其中初始標記辞嗡、重新標記這兩步驟仍需要 “Stop The World”
  • 優(yōu)點:并發(fā)收集、低停頓
  • 缺點:產(chǎn)生大量的空間碎片滞造,并發(fā)階段會降低吞吐量

G1 收集器

  • G1 收集器是目前技術(shù)發(fā)展最前沿的成功之一,與CMS相比:
    • 空間整合:G1 收集器采用”標記-壓縮“算法栋烤,不會產(chǎn)生內(nèi)存碎片谒养,分配大對象時不會因為找不到連續(xù)空間而提前觸發(fā)下一次 GC
    • 可預(yù)測停頓:G1 追求低停頓時間外,還能建立可預(yù)測停頓時間模型明郭,能讓使用者指定在一個長度為 N 的毫秒時間片段內(nèi)买窟,消耗在垃圾收集上的時間不得超過 N 毫秒
    • G1 收集器時,它將整個 Java 堆劃分為多個大小相等的區(qū)域薯定,雖然還保留新生代和老年代的概念始绍,但新生代和老年代不再是物理隔閡,他們都是一部分(可以不連續(xù))Region 的集合话侄。當新生代占用達到一定比例時亏推,開始出發(fā)收集
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市年堆,隨后出現(xiàn)的幾起案子吞杭,更是在濱河造成了極大的恐慌,老刑警劉巖变丧,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芽狗,死亡現(xiàn)場離奇詭異,居然都是意外死亡痒蓬,警方通過查閱死者的電腦和手機童擎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來攻晒,“玉大人顾复,你說我怎么就攤上這事⊙妆妫” “怎么了捕透?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我乙嘀,道長末购,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任虎谢,我火速辦了婚禮盟榴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘婴噩。我一直安慰自己擎场,他們只是感情好,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布几莽。 她就那樣靜靜地躺著迅办,像睡著了一般。 火紅的嫁衣襯著肌膚如雪章蚣。 梳的紋絲不亂的頭發(fā)上站欺,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機與錄音纤垂,去河邊找鬼矾策。 笑死,一個胖子當著我的面吹牛峭沦,可吹牛的內(nèi)容都是我干的贾虽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼吼鱼,長吁一口氣:“原來是場噩夢啊……” “哼蓬豁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起菇肃,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤庆尘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后巷送,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體驶忌,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年笑跛,在試婚紗的時候發(fā)現(xiàn)自己被綠了付魔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡飞蹂,死狀恐怖几苍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情陈哑,我是刑警寧澤妻坝,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布伸眶,位于F島的核電站,受9級特大地震影響刽宪,放射性物質(zhì)發(fā)生泄漏厘贼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一圣拄、第九天 我趴在偏房一處隱蔽的房頂上張望嘴秸。 院中可真熱鬧,春花似錦庇谆、人聲如沸岳掐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽串述。三九已至,卻和暖如春寞肖,著一層夾襖步出監(jiān)牢的瞬間剖煌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工逝淹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人桶唐。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓栅葡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親尤泽。 傳聞我的和親對象是個殘疾皇子欣簇,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

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

  • 1.什么是垃圾回收? 垃圾回收(Garbage Collection)是Java虛擬機(JVM)垃圾回收器提供...
    簡欲明心閱讀 89,507評論 17 311
  • 一. 垃圾回收的意義 在C++中坯约,對象所占的內(nèi)存在程序結(jié)束運行之前一直被占用熊咽,在明確釋放之前不能分配給其它對...
    Stan_Z閱讀 1,934評論 0 25
  • 原文閱讀 前言 這段時間懈怠了,罪過闹丐! 最近看到有同事也開始用上了微信公眾號寫博客了横殴,挺好的~給他們點贊,這博客我...
    碼農(nóng)戲碼閱讀 5,979評論 2 31
  • 這篇文章是我之前翻閱了不少的書籍以及從網(wǎng)絡(luò)上收集的一些資料的整理卿拴,因此不免有一些不準確的地方衫仑,同時不同JDK版本的...
    高廣超閱讀 15,614評論 3 83
  • 愛情里的天真女人 超愛做夢 潛意識里 全是與他的地老天荒 只愿自己 長睡不愿醒 以為夢會成真 愛情里的男人 是天真...
    梅蕊新說閱讀 270評論 4 29