深入理解JVM系列-1

一、java內(nèi)存模型

要深入了解jvm之前,需要對java內(nèi)存結(jié)構(gòu)有清楚的認(rèn)識,我們先通過一個簡單的demo來了解java內(nèi)存模型戳杀。
有如下兩個類,我們通過它的執(zhí)行順序來觀察內(nèi)存中的變化

class A{
  static B b = new B();

  public static void main(String[] args){
    fun1();
    fun2();
  }

  public static void fun1(){
    B b1 = new B();
    b1.load();
  }

  public static void fun2(){
    b.load();
  }
}

class B{
  public void load(){}
}

當(dāng)class A中的main方法啟動的時候內(nèi)存中需要做的操作

1夭苗、加載類A,B到j(luò)ava內(nèi)存中

類加載到內(nèi)存中的時候,我們必然有一塊區(qū)域來存放這些加載的類的數(shù)據(jù)隔缀,這塊區(qū)域我們稱之為方法區(qū)题造,在jdk8之后方法區(qū)的概念被元空間(Metaspace)取代。元空間相比于方法區(qū)靈活很多猾瘸。比如可以動態(tài)分配元空間大小界赔,通過指針和其他方式來表示類和元數(shù)據(jù),可以更有效的利用內(nèi)存牵触。為了統(tǒng)一概念淮悼,我們接下來的介紹全部稱之為方法區(qū)。
如下圖揽思,會把A,B的字節(jié)碼文件加載到內(nèi)存中的方法區(qū)袜腥。

1.png

2、執(zhí)行main方法

類加載之后執(zhí)行main方法的時候也有一塊區(qū)域來對應(yīng)方法的執(zhí)行钉汗,稱之為棧羹令。棧的數(shù)據(jù)結(jié)構(gòu)決定了他的特點 先進(jìn)后出鲤屡。main方法執(zhí)行的時候需要先開啟一個main線程來執(zhí)行字節(jié)碼文件。而java又可以支持多線程福侈,此時就需要一個東西來記錄每個線程執(zhí)行到哪一行代碼酒来。這個記錄代碼行數(shù)的東西叫程序計數(shù)器。那么此時的內(nèi)存模型為:


2.png

當(dāng)main方法執(zhí)行的時候會調(diào)用fun1和fun2肪凛。在fun1中創(chuàng)建了一個對象b1堰汉,fun2中使用了靜態(tài)對象b(靜態(tài)對象的初始化隨著類的加載而加載,為了更好的延申出堆的概念故在此處提出)伟墙。這些對象的創(chuàng)建需要對應(yīng)一塊內(nèi)存區(qū)域翘鸭,此塊內(nèi)存區(qū)域就是堆。
此時的內(nèi)存模型為:


3.png

3远荠、方法執(zhí)行完畢釋放資源

當(dāng)所有方法執(zhí)行完之后矮固,方法需要出棧(又成彈棧),此時可以看到main方法在最下面(壓棧)譬淳,先進(jìn)后出因此fun2,fun1,main依次出棧档址。出棧之后棧里面內(nèi)存得到釋放,但是堆里面的對象此時b還是被static b引用邻梆,而b1此時沒有任何人引用守伸。所以b1對應(yīng)的堆內(nèi)存就成了垃圾需要被釋放。但是java的內(nèi)存回收機(jī)制并不是沒有引用就立馬會回收浦妄。當(dāng)堆內(nèi)存不足的時候才會觸發(fā)內(nèi)存回收機(jī)制尼摹,jvm才會開始回收這些內(nèi)存垃圾。

二剂娄、新生代蠢涝,老年代、永久代的概念

1阅懦、永久代:永久存在與jvm內(nèi)存中的數(shù)據(jù)和二。方法區(qū)就是永久代。

2耳胎、新生代:新創(chuàng)建的對象所在的位置惯吕。

還是看上圖的內(nèi)存模型,每次new出來的對象都會放到堆里面怕午,這批對象存儲的位置在堆中又有細(xì)分废登,分為新生代和老年代,新生代就是用于存方這些對象的地方郁惜。

3堡距、老年代:年紀(jì)大的對象。

當(dāng)堆內(nèi)存快要滿的時候,會觸發(fā)jvm垃圾回收機(jī)制吏颖,此時無引用的內(nèi)存垃圾就會被釋放掉搔体,有引用的對象會被保留,每經(jīng)過一次垃圾回收被保留下來的對象的年齡就會+1半醉。jvm默認(rèn)年齡>15的對象就會被移入老年代疚俱。還有一種情況會放入老年代,后面再講缩多。

三呆奕、Eden區(qū)和Survivore區(qū)

系統(tǒng)的內(nèi)存都是連續(xù)的,當(dāng)需要使用內(nèi)存的時候會在空閑內(nèi)存之后連續(xù)開辟一塊新的內(nèi)存以供使用衬吆。而jvm觸發(fā)垃圾回收機(jī)制時梁钾,回收新生代無引用的數(shù)據(jù),當(dāng)這些垃圾被回收之后就會出現(xiàn)一種情況逊抡,被留下的有引用的數(shù)據(jù)之間存在內(nèi)存碎片姆泻,此時就會導(dǎo)致內(nèi)存不再連續(xù)。會影響接下來的內(nèi)存分配使用冒嫡。因此衍生出了E區(qū)和S區(qū)的概念拇勃。

所有new出來的對象全部放到E區(qū),當(dāng)E區(qū)要滿的時候觸發(fā)新生代垃圾回收機(jī)制(Young GC 或者叫Minor GC)孝凌,此時會把E區(qū)所有垃圾全部釋放方咆,并且把存活下來的對象使用復(fù)制算法重新整理內(nèi)存放入到S區(qū),并把這批對象年齡+1蟀架。這樣就保證了E區(qū)的空間永遠(yuǎn)是連續(xù)的瓣赂。

但是這樣還有問題,第二次垃圾回收的時候如何處理片拍,因為此時S區(qū)被上一次存活的對象占用了空間煌集,這一批存活的對象該如何整理內(nèi)存,該放在哪里呢捌省?
對于這一問題牙勘,其實也很簡單,再增加一個S區(qū)即可所禀,永遠(yuǎn)空出來一個S區(qū)用于整理內(nèi)存和存放存活對象。因此放钦,堆內(nèi)存空間整體模型就出來了色徘。


image.png

四、哪些對象會被回收

大致了解了新生代模型之后我們來想一個問題操禀,jvm如何判斷什么數(shù)據(jù)需要被回收的褂策。

jvm每次內(nèi)存回收的時候都會采用一種 可達(dá)性分析算法 來判定該對象是否可以被回收。這個算法的意思就是分析誰在引用這個對象 一級一級向上找,看是否有GC Roots斤寂。

那什么又是GC Roots 呢耿焊,GC Roots有一下幾種
1、在虛擬機(jī)棧(棧幀中的本地變量表)中引用的對象遍搞,譬如各個線程被調(diào)用的方法堆棧中使用到的參數(shù)罗侯、局部變量、臨時變量等溪猿。
2钩杰、在方法區(qū)中類靜態(tài)屬性引用的對象,譬如Java類的引用類型靜態(tài)變量诊县。
3讲弄、在方法區(qū)中常量引用的對象,譬如字符串常量池(String Table)里的引用依痊。
4避除、本地方法棧中 JNI(Native方法)引用的對象
5、Java虛擬機(jī)內(nèi)部的引用胸嘁,如基本數(shù)據(jù)類型對應(yīng)的Class對象瓶摆,一些常駐的異常對象(比如NullPointExcepiton、OutOfMemoryError)等缴渊,還有系統(tǒng)類加載器赏壹。
6、所有被同步鎖(synchronized關(guān)鍵字)持有的對象衔沼。
6蝌借、反映Java虛擬機(jī)內(nèi)部情況的JMXBean、JVMTI中注冊的回調(diào)指蚁、本地代碼緩存等菩佑。
7、根據(jù)用戶所選用的垃圾收集器以及當(dāng)前回收的內(nèi)存區(qū)域不 同凝化,“臨時性”地加入的其他對象稍坯。
在我們代碼中常見的GC Roots 主要包含:棧正在使用的對象,局部變量搓劫,靜態(tài)變量瞧哟。

java中的引用分為強(qiáng)引用,弱引用枪向,軟引用勤揩,虛引用。此次不在延申這些引用的用法秘蛔。對與垃圾回收來說陨亡,強(qiáng)引用 并且有GC Roots的對象不會被回收傍衡。其他引用不管有沒有GC Roots都會被回收。

未完待續(xù)~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末负蠕,一起剝皮案震驚了整個濱河市蛙埂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌遮糖,老刑警劉巖绣的,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異止吁,居然都是意外死亡被辑,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門敬惦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盼理,“玉大人,你說我怎么就攤上這事俄删『暾” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵畴椰,是天一觀的道長臊诊。 經(jīng)常有香客問我,道長斜脂,這世上最難降的妖魔是什么抓艳? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮帚戳,結(jié)果婚禮上玷或,老公的妹妹穿的比我還像新娘。我一直安慰自己片任,他們只是感情好偏友,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著对供,像睡著了一般位他。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上产场,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天鹅髓,我揣著相機(jī)與錄音,去河邊找鬼京景。 笑死迈勋,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的醋粟。 我是一名探鬼主播靡菇,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼米愿!你這毒婦竟也來了厦凤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤育苟,失蹤者是張志新(化名)和其女友劉穎较鼓,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體违柏,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡博烂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了漱竖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片禽篱。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖馍惹,靈堂內(nèi)的尸體忽然破棺而出躺率,到底是詐尸還是另有隱情,我是刑警寧澤万矾,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布悼吱,位于F島的核電站,受9級特大地震影響良狈,放射性物質(zhì)發(fā)生泄漏后添。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一薪丁、第九天 我趴在偏房一處隱蔽的房頂上張望遇西。 院中可真熱鬧,春花似錦窥突、人聲如沸努溃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽梧税。三九已至,卻和暖如春称近,著一層夾襖步出監(jiān)牢的瞬間第队,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工刨秆, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留凳谦,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓衡未,卻偏偏與公主長得像尸执,于是被迫代替她去往敵國和親家凯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

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