從HelloWo從HelloWorld.class講內(nèi)存到底是如何進行分配的?

很多人問,作為一個Android開發(fā)有必要了解Java內(nèi)存分配機制嗎严嗜?答案是肯定的。

java的內(nèi)存區(qū)域劃分實際上遠比這復(fù)雜:java虛擬機在執(zhí)行Java
程序的過程中會把所有的內(nèi)存劃分為不同的數(shù)據(jù)區(qū)域洲敢,下面這張圖
描述了一個HelloWorld.java文件被JVM加載到內(nèi)存中的過程:


1.HelloWorld.java 文件首先需要經(jīng)過編譯器編譯漫玄,生成HelloWorld.class 字節(jié)碼文件。

2.Java程序中訪問HelloWorld這個類時压彭,需要通過ClassLoader將HelloWorld.class加載到JVM內(nèi)存中睦优。

3.JVM中的內(nèi)存可以劃分為若干個不同的數(shù)據(jù)區(qū)域,包括:
程序計數(shù)器壮不,虛擬機棧汗盘,本地方法棧,堆询一,方法區(qū)隐孽。

1.1 程序計數(shù)器

Java是多線程的,CPU可以在多個線程中分配執(zhí)行時間片段健蕊。當一個線程被CPU掛起時菱阵,需要記錄代碼已經(jīng)執(zhí)行到的位置,方便CPU重新執(zhí)行此線程時缩功,知道從那行執(zhí)行開始執(zhí)行晴及,這就是程序計數(shù)器的組作用。

程序計數(shù)器是虛擬機中一塊較小的內(nèi)存空間嫡锌,主要用于記錄當前線程
執(zhí)行的位置虑稼。


如上圖所示:每個線程都會記錄當前方法執(zhí)行到的一個位置,當CPU切換到某一個線程上時势木,根據(jù)程序計數(shù)器記錄的數(shù)字动雹,繼續(xù)向下執(zhí)行指令。

關(guān)于程序計數(shù)器還有幾個需要格外注意:

1.在Java虛擬機規(guī)范中跟压,對程序計數(shù)器這一區(qū)域規(guī)定沒有任何OutOfMemoryError情況。

2.線程私有歼培,每個線程內(nèi)部都有一個私有的程序計數(shù)器震蒋,他的生命周期隨著線程創(chuàng)建而創(chuàng)建茸塞,結(jié)束而死亡。

3.當一個線程正在執(zhí)行一個Java方法時查剖,這個程序計數(shù)器記錄正在執(zhí)行虛擬機字節(jié)指令的地址钾虐,如果正在執(zhí)行的是Native方法,這個程序計數(shù)器的數(shù)值為空

1.2本地方法棧

本地方法棧和下面即將要講的虛擬機椝褡基本相同效扫,只不過是針對本地方法,在Android開發(fā)涉及JNI可能接觸本地方法多一些直砂,有一些虛擬機的實現(xiàn)已經(jīng)將本地方法棧和虛擬機棧合二為一了(HotSpot)菌仁。

1.3虛擬機棧

虛擬機棧也是線程私有的,與線程的生命周期同步静暂,在Java虛擬機中济丘,規(guī)定了兩種異常:

1.StackOverflowError :當前線程請求棧深度超出虛擬機棧所允許的深度時拋出。

2.OutOfMemoryError:當JVM動態(tài)擴展到無法申請足夠內(nèi)存時拋出洽蛀。

在我們看一些博客和書的時候摹迷,經(jīng)常看到一句話:JVM是基于棧解釋器執(zhí)行的郊供,DVM是基于寄存器解釋器執(zhí)行的峡碉。

上面那句話基于棧值得就是虛擬機棧,虛擬機棧的初衷是用來描述Java方法執(zhí)行的內(nèi)存模型驮审,每個方法執(zhí)行的時候鲫寄,JVM都會在虛擬機棧中創(chuàng)建一個棧幀,讓我們看一下棧幀是什么头岔?

1.3.1棧幀

每一個線程在執(zhí)行某一個方法時塔拳,都會為這個方法創(chuàng)建一個棧幀,
我們可以這樣理解:一個線程包含多個棧幀峡竣,每個棧幀內(nèi)部包含:局部變量表靠抑,操作數(shù)棧,動態(tài)鏈接适掰,返回地址等颂碧。


1.3.1.1 局部變量表

局部變量表是變量值的存儲空間,我們調(diào)用方法傳遞的參數(shù)类浪,以及在方法內(nèi)部創(chuàng)建的變量都會保存在局部變量表中载城。

1.3.1.2 操作數(shù)棧

操作數(shù)棧也常稱為操作棧,他是一個后入先出棧费就。
當一個方法剛剛開始執(zhí)行的時候诉瓦,這個方法的操作數(shù)棧是空的,在方法執(zhí)行的過程中,會把各種指令壓入和彈出操作數(shù)棧睬澡。

1.3.1.3 動態(tài)鏈接

動態(tài)鏈接的主要目的是為了支持方法在調(diào)用過程中的動態(tài)鏈接固额。

在一個class文件中,一個方法要調(diào)用其他方法煞聪,需要將這些方法的符號引用轉(zhuǎn)化為其所在內(nèi)存地址中的直接引用斗躏,而符號引用存在于方法區(qū)中。

1.3.1.4 返回地址

當一個方法開始執(zhí)行后昔脯,只有兩種方式可以退出這個方法:

1.正常退出:方法中的代碼正常完成啄糙,或者遇到任意一個返回的指令。
2.異常退出:方法執(zhí)行過程中遇到異常云稚,并且內(nèi)部沒有處理隧饼。

正常退出時,棧幀中可能保存此數(shù)值作為返回地址碱鳞。方法異常退出時桑李,棧幀中一般不會保存部分信息。

1.4 堆

Java堆是JVM所管理的內(nèi)存中最大的一塊窿给,該區(qū)的唯一目的就是存放對象實例贵白,幾乎所有的對象的實例都在堆里分配,因此他是GC管理的主要區(qū)域崩泡,有時候也叫GC堆同時他是所有線程的內(nèi)存區(qū)域禁荒,因此被分配在此區(qū)域的對象如果被多個線程訪問的話,需要考慮線程安全角撞。

按照對象存儲時間的不同呛伴,可以分為新生代,老年代谒所,其中新生代又被分為Eden和Survivor區(qū)热康。

圖中不同的區(qū)域具有不同的生命周期,可以根據(jù)不同區(qū)域使用不同的垃圾回收算法劣领,進而提高垃圾回收率姐军。

1.5 方法區(qū)

方法區(qū)也是JVM規(guī)范里規(guī)定的一塊運行時數(shù)據(jù)區(qū)。主要存儲已經(jīng)被JVM加載的類信息(版本尖淘,字段奕锌,方法,接口)村生,常量惊暴,靜態(tài)變量,即時編譯器后的代碼和數(shù)據(jù)趁桃,該區(qū)域也是被各個線程共享辽话。

1.6 異常再現(xiàn)

StackOverflowError 棧溢出:

在method方法中肄鸽,遞歸調(diào)用了自身,并且沒有設(shè)置遞歸結(jié)束條件屡穗,所以出現(xiàn)了StackOverflowError異常贴捡。

OutOfMemoryError 內(nèi)存溢出:
理論上,虛擬機棧村砂,方法去,堆都有可能發(fā)生OutOfMemoryError屹逛,但在實際過程中础废,大多數(shù)發(fā)生于堆中。

在一個無線循環(huán)中罕模,動態(tài)向List添加HeapError對象评腺,這會不斷的占用堆中的內(nèi)存,當堆內(nèi)存不夠時淑掌,必然會產(chǎn)生OutOfMemoryError蒿讥,也就是內(nèi)存溢出異常。

1.7 總結(jié)

對于 JVM 運行時內(nèi)存布局抛腕,我們需要始終記住一點:上面介紹的這 5 塊內(nèi)容都是在 Java 虛擬機規(guī)范中定義的規(guī)則芋绸,這些規(guī)則只是描述了各個區(qū)域是負責做什么事情、存儲什么樣的數(shù)據(jù)担敌、如何處理異常摔敛、是否允許線程間共享等。千萬不要將它們理解為虛擬機的“具體實現(xiàn)”全封,虛擬機的具體實現(xiàn)有很多马昙,比如 Sun 公司的 HotSpot、JRocket刹悴、IBM J9行楞、以及我們非常熟悉的 Android Dalvik 和 ART 等。這些具體實現(xiàn)在符合上面 5 種運行時數(shù)據(jù)區(qū)的前提下土匀,又各自有不同的實現(xiàn)方式子房。

最后我們借助一張圖來概括一下本課時所介紹的內(nèi)容:


總結(jié)來說,JVM 的運行時內(nèi)存結(jié)構(gòu)中一共有兩個“椇阆鳎”和一個“堆”池颈,分別是:Java 虛擬機棧和本地方法棧,以及“GC堆”和方法區(qū)钓丰。除此之外還有一個程序計數(shù)器躯砰,但是我們開發(fā)者幾乎不會用到這一部分,所以并不是重點學(xué)習(xí)內(nèi)容携丁。 JVM 內(nèi)存中只有堆和方法區(qū)是線程共享的數(shù)據(jù)區(qū)域琢歇,其它區(qū)域都是線程私有的兰怠。并且程序計數(shù)器是唯一一個在 Java 虛擬機規(guī)范中沒有規(guī)定任何 OutOfMemoryError 情況的區(qū)域。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末李茫,一起剝皮案震驚了整個濱河市揭保,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌魄宏,老刑警劉巖秸侣,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帐萎,死亡現(xiàn)場離奇詭異陨仅,居然都是意外死亡,警方通過查閱死者的電腦和手機良价,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門予跌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搏色,“玉大人,你說我怎么就攤上這事券册∑到危” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵烁焙,是天一觀的道長。 經(jīng)常有香客問我考阱,道長翠忠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任乞榨,我火速辦了婚禮秽之,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吃既。我一直安慰自己考榨,他們只是感情好,可當我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布鹦倚。 她就那樣靜靜地躺著河质,像睡著了一般。 火紅的嫁衣襯著肌膚如雪震叙。 梳的紋絲不亂的頭發(fā)上掀鹅,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天,我揣著相機與錄音媒楼,去河邊找鬼乐尊。 笑死,一個胖子當著我的面吹牛划址,可吹牛的內(nèi)容都是我干的扔嵌。 我是一名探鬼主播限府,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼痢缎!你這毒婦竟也來了胁勺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤独旷,失蹤者是張志新(化名)和其女友劉穎署穗,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嵌洼,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡蛇捌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了咱台。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡俭驮,死狀恐怖回溺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情混萝,我是刑警寧澤遗遵,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站逸嘀,受9級特大地震影響车要,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜崭倘,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一翼岁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧司光,春花似錦琅坡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至坞淮,卻和暖如春茴晋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背回窘。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工诺擅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人毫玖。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓掀虎,卻偏偏與公主長得像凌盯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子烹玉,可洞房花燭夜當晚...
    茶點故事閱讀 45,440評論 2 359

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

  • 如果有需要,書籍地址 JVM 中的內(nèi)存可以劃分為若干個不同的數(shù)據(jù)區(qū)域继效,主要分為:程序計數(shù)器症杏、虛擬機棧、本地方法棧瑞信、...
    XII01閱讀 425評論 0 0
  • Java內(nèi)存區(qū)域直接劃分為堆內(nèi)存和棧內(nèi)存并不完全準確 JVM 中的內(nèi)存可以劃分為若干個不同的數(shù)據(jù)區(qū)域凡简,主要分為:程...
    NC丶腦補東閱讀 565評論 0 4
  • 久違的晴天逼友,家長會。 家長大會開好到教室時秤涩,離放學(xué)已經(jīng)沒多少時間了帜乞。班主任說已經(jīng)安排了三個家長分享經(jīng)驗。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,524評論 16 22
  • 今天感恩節(jié)哎筐眷,感謝一直在我身邊的親朋好友黎烈。感恩相遇!感恩不離不棄匀谣。 中午開了第一次的黨會照棋,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,567評論 0 11
  • 可愛進取,孤獨成精振定。努力飛翔必怜,天堂翱翔。戰(zhàn)爭美好后频,孤獨進取梳庆。膽大飛翔,成就輝煌卑惜。努力進取膏执,遙望,和諧家園露久「祝可愛游走...
    趙原野閱讀 2,735評論 1 1