Java架構(gòu)師JVM啟動流程和內(nèi)存結(jié)構(gòu),程序員必看状共!

JVM是Java程序運行的環(huán)境峡继,同時是一個操作系統(tǒng)的一個應(yīng)用程序進(jìn)程匈挖,因此它有自己的生命周期,也有自己的代碼和數(shù)據(jù)空間。

JVM工作原理和特點主要是指操作系統(tǒng)裝入JVM舶吗,是通過jdk中Java.exe來完成誓琼,通過下面4步來完成JVM環(huán)境。

1.創(chuàng)建JVM裝載環(huán)境和配置

JVM裝入環(huán)境叔收,JVM提供的方式是操作系統(tǒng)的動態(tài)連接文件

2.裝載JVM.dll

通過第一步已經(jīng)找到了JVM的路徑饺律,Java通過LoadJavaVM來裝入JVM.dll文件.裝入工作很簡單就是調(diào)用Windows API函數(shù):

LoadLibrary裝載JVM.dll動態(tài)連接庫.然后把JVM.dll中的導(dǎo)出函數(shù)JNI_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs掛接到InvocationFunctions變量的CreateJavaVM和GetDefaultJavaVMInitArgs函數(shù)指針變量上复濒。JVM.dll的裝載工作宣告完成巧颈。

3.初始化JVM.dll并掛界到JNIENV(JNI調(diào)用接口)實例

這樣就可以在Java中調(diào)用JVM的函數(shù)了.調(diào)用InvocationFunctions->CreateJavaVM也就是JVM中JNI_CreateJavaVM方法獲得JNIEnv結(jié)構(gòu)的實例.

4.調(diào)用JNIEnv實例裝載并處理class類洛二。

JVM基本結(jié)構(gòu)

? ? ? ? JVM體系主要是兩個JVM的內(nèi)部體系結(jié)構(gòu)分為三個子系統(tǒng)和兩大組件晾嘶,分別是:類裝載器(ClassLoader)子系統(tǒng)娶吞、執(zhí)行引擎子系統(tǒng)和GC子系統(tǒng)妒蛇,組件是內(nèi)存運行數(shù)據(jù)區(qū)域和本地接口。

?

· 程序計數(shù)器(PC寄存器)

PC(Program Couneter)寄存器是每個線程私有的吏奸,Java虛擬機會為每個線程創(chuàng)建PC寄存器奋蔚,在任意時刻泊碑,一個Java線程總是在執(zhí)行一個方法馒过,這個方法稱為當(dāng)前方法,如果當(dāng)前方法不是本地方法来累,PC寄存器總會執(zhí)行當(dāng)前正在被執(zhí)行的指令佃扼,如果是本地方法蔼夜,則PC寄存器值為Underfined求冷。每執(zhí)行一條指令 PC 都會自增,因此 PC 存儲了指向下一條要被執(zhí)行的指令地址拯坟。JVM 用 PC 來跟蹤指令執(zhí)行的位置郁季,PC 將實際上是指向方法區(qū)(Method Area)的一個內(nèi)存地址钱磅。

· 方法區(qū)(永久代)

方法區(qū)存儲了每個類的信息年柠,比如類型的常量池褪迟、字段,方法信息掀抹、方法字節(jié)碼傲武。所有線程共享同一個方法區(qū)谱轨,因此訪問方法區(qū)數(shù)據(jù)的和動態(tài)鏈接的進(jìn)程必須線程安全土童。如果兩個線程試圖訪問一個還未加載的類的字段或方法工坊,必須只加載一次王污,而且兩個線程必須等它加載完畢才能繼續(xù)執(zhí)行。

(JDK1.7中尿招,已經(jīng)把放在永久代的字符串常量池移到堆中就谜。JDK1.8撤銷永久代丧荐,引入元空間喧枷。元空間是直接存在內(nèi)存中,不在java虛擬機中的车荔,因此元空間依賴于內(nèi)存大小夸赫。當(dāng)然你也可以自定義元空間大小茬腿。)

· 方法區(qū)不需要連續(xù)的內(nèi)存宜雀,可以選擇固定大小或者可擴展辐董。并且還可以選擇不實現(xiàn)垃圾收集。相對而言苔严,垃圾收集行為在這個區(qū)域是比較少出現(xiàn)的,但并非數(shù)據(jù)進(jìn)入了方法區(qū)就如永久代的名字一樣“永久”存在了欠窒。這個區(qū)域的內(nèi)存回收目標(biāo)主要是針對常量池的回收和對類型的卸載岖妄,一般來說這個區(qū)域的回收“成績”比較難以令人滿意寂祥,尤其是類型的卸載,條件相當(dāng)苛刻福扬,但是這部分區(qū)域的回收確實是有必要的忧换。當(dāng)方法區(qū)無法滿足內(nèi)存分配需求時,將拋出OutOfMemoryError異常亚茬。

· 堆(Heap)

應(yīng)用系統(tǒng)對象都保存在Java堆中刹缝,堆被用來在運行時分配類實例梢夯、數(shù)組晴圾。不能在棧上存儲數(shù)組和對象。因為棧幀被設(shè)計為創(chuàng)建以后無法調(diào)整大小人乓。棧幀只存儲指向堆中對象或數(shù)組的引用色罚。與局部變量數(shù)組(每個棧幀中的)中的原始類型和引用類型不同账劲,對象總是存儲在堆上以便在方法結(jié)束時不會被移除金抡。對象只能由垃圾回收器移除梗肝。所有線程共享Java堆巫击。

簡述垃圾回收

為了支持分代垃圾回收機制柄粹,堆內(nèi)存可以劃分為新生代和老年代兩個區(qū)域(默認(rèn)新生代與老年代的空間大小為1:2)匆绣。新生代可以再劃分為Eden區(qū)崎淳、From Survivor區(qū)和To Survivor區(qū)(三者比例為8:1:1)。幾乎所有的新對象的創(chuàng)建都是在Eden區(qū)進(jìn)行的森爽。在垃圾回收(GC)過程中嚣镜,Eden中的活躍對象會被轉(zhuǎn)移到Survivor區(qū)菊匿,當(dāng)再到達(dá)一定的年齡(經(jīng)歷過的Minor GC的次數(shù)跌捆,每經(jīng)過一次新生代回收,如果對象存活則它的年齡就加1姆钉,對象達(dá)到一定的年齡后)抄瓦,會被轉(zhuǎn)移到老年代中钙姊。

· Java棧(Java Stack)

Java棧是線程私有的內(nèi)存區(qū)域摸恍,其中存儲的是棧幀赤屋。类早,每一次方法調(diào)用創(chuàng)建一個幀嗜逻,并壓棧,調(diào)用完畢出棧逆日。下面是內(nèi)存的線程公有私有示意圖:

如果方法methodOne方法調(diào)用了methodTwo室抽,那么methodOne就會先入棧創(chuàng)建一個棧楨坪圾,接著methodTwo再入棧成為棧頂(假設(shè)沒有其他的方法執(zhí)行)兽泄,methodTwo執(zhí)行完先出棧,接著methodOne執(zhí)行完出棧病梢。

一般由三部分組成:局部變量表蜓陌、操作數(shù)據(jù)棧和幀數(shù)據(jù)區(qū)

局部變量表:可以存放的數(shù)據(jù)有8種基本數(shù)據(jù)類型(boolean护奈,byte哥纫,char蛀骇,short擅憔,int,float蚌讼,long,double)芥喇,對象引用和returnAddress類型继控。其中l(wèi)ong和double因為是64位胖眷,會占用兩個局部變量的空間珊搀。

每一個塊就是一個棧食棕,如圖是兩個棧

在Java虛擬機規(guī)范中簿晓,對這個區(qū)域規(guī)定了兩種異常狀況:如果線程請求的棧深度大于虛擬機所允許的深度(比如遞歸調(diào)用的y時候)千埃,將拋出StackOverflowError異常;如果虛擬機椱司剩可以動態(tài)擴展(當(dāng)前大部分的Java虛擬機都可動態(tài)擴展蜈缤,只不過Java虛擬機規(guī)范中也允許固定長度的虛擬機棧)底哥,當(dāng)擴展時無法申請到足夠的內(nèi)存時會拋出OutOfMemoryError異常趾徽。

操作數(shù)棧:主要保存計算過程的中間結(jié)果孵奶,同時作為計算過程中的變量臨時的存儲空間了袁。? 下圖是一個兩數(shù)相加的操作數(shù)棧的過程:

so?Bz#+??

幀數(shù)據(jù)區(qū):除了局部變量表和操作數(shù)據(jù)棧以外载绿,棧還需要一些數(shù)據(jù)來支持常量池的解析卢鹦,這里幀數(shù)據(jù)區(qū)保存著訪問常量池的指針冀自,方便計程序訪問常量池,另外當(dāng)函數(shù)返回或出現(xiàn)異常時賣虛擬機子必須有一個異常處理表搀玖,方便發(fā)送異常的時候找到異常的代碼灌诅,因此異常處理表也是幀數(shù)據(jù)區(qū)的一部分猜拾。

棧上分配

? 小對象(一般幾十個bytes)挎袜,在沒有逃逸的情況下盯仪,可以直接分配在棧上

直接分配在棧上全景,可以自動回收爸黄,減輕GC壓力

大對象或者逃逸對象無法棧上分配

· 本地方法棧(Native Method Stack)

本地方法棧也是線程私有的內(nèi)存區(qū)域奔浅,與java棧比較相似鲁驶,不同之處在于該區(qū)域主要是保存Native方法相關(guān)的數(shù)據(jù)。Native方法是非Java語言編寫的方法舞骆。

與虛擬機棧一樣钥弯,本地方法棧區(qū)域也會拋出StackOverflowError和OutOfMemoryError異常径荔。

專注于Java架構(gòu)師技術(shù)分享,撩我免費送Java全套架構(gòu)師晉級資料

(Java架構(gòu)師交流企Q鵝裙*/*:445*-*820*-*908 )

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末脆霎,一起剝皮案震驚了整個濱河市总处,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌睛蛛,老刑警劉巖鹦马,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異忆肾,居然都是意外死亡荸频,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門旭从,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渠缕,“玉大人澜汤,你說我怎么就攤上這事谁不。” “怎么了偷溺?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵尉共,是天一觀的道長殿托。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么叹坦? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮篮赢,結(jié)果婚禮上示辈,老公的妹妹穿的比我還像新娘。我一直安慰自己弄喘,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布羊始。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪桥滨。 梳的紋絲不亂的頭發(fā)上纷跛,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天拷恨,我揣著相機與錄音勒叠,去河邊找鬼柒桑。 笑死,一個胖子當(dāng)著我的面吹牛纺座,可吹牛的內(nèi)容都是我干的馋贤。 我是一名探鬼主播扰付,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤洁奈,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體玛追,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡击狮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了驮配。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖多搀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤鳖孤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布拧晕,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏叶圃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一箕慧、第九天 我趴在偏房一處隱蔽的房頂上張望颠焦。 院中可真熱鬧分冈,春花似錦、人聲如沸饺著。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽功咒。三九已至榜旦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肉盹,已是汗流浹背疹尾。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工上忍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人纳本。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓窍蓝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親繁成。 傳聞我的和親對象是個殘疾皇子吓笙,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,077評論 2 355

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

  • 內(nèi)存溢出和內(nèi)存泄漏的區(qū)別 內(nèi)存溢出:out of memory,是指程序在申請內(nèi)存時巾腕,沒有足夠的內(nèi)存空間供其使用面睛,...
    Aimerwhy閱讀 743評論 0 1
  • 第二部分 自動內(nèi)存管理機制 第二章 java內(nèi)存異常與內(nèi)存溢出異常 運行數(shù)據(jù)區(qū)域 程序計數(shù)器:當(dāng)前線程所執(zhí)行的字節(jié)...
    小明oh閱讀 1,172評論 0 2
  • 注1:以下所提及線程,無特定說明的均默認(rèn)指代“Java虛擬機線程”尊搬。 注2:注意避免混淆Stack叁鉴、Heap和Ja...
    亨小利霍閱讀 665評論 1 4
  • 婚姻的初始,所有人都說那是兩個人的事毁嗦,所有的長輩親戚都說:“只要他們倆好亲茅,我們怎么著都行”,而事實并非如此狗准。 當(dāng)婚...
    玉生煙閱讀 179評論 0 1
  • 今年生日克锣,終于實現(xiàn)了自己的小目標(biāo),滿心歡喜腔长。懷著對職業(yè)的崇高理想袭祟,對孩子的無限向往,我來到這里捞附。 現(xiàn)實卻給了我狠狠...
    沂南036張霞閱讀 308評論 0 2