初識(shí)JVM-JVM內(nèi)存結(jié)構(gòu)

1 前言

什么是JVM?我們來看一下維基百科的答案

A Java virtual machine (JVM) is a virtual machine that enables a computer to run Java programs as well as programs written in other languages and compiled to Java bytecode. The JVM is detailed by a specification that formally describes what is required of a JVM implementation. Having a specification ensures interoperability of Java programs across different implementations so that program authors using the Java Development Kit (JDK) need not worry about idiosyncrasies of the underlying hardware platform.

Java虛擬機(jī)(JVM)是一種虛擬機(jī)檐什,它使計(jì)算機(jī)能夠運(yùn)行Java程序以及用其他語言編寫的程序(如Groovy,Scala)输枯,并編譯成Java字節(jié)碼。JVM由規(guī)范描述了JVM實(shí)現(xiàn)所需的規(guī)范。使用規(guī)范確保Java程序在不同實(shí)現(xiàn)之間的互操作性,以便使用Java開發(fā)工具包(JDK)的程序作者不必?fù)?dān)心底層硬件平臺(tái)的特質(zhì)。
其中虛擬機(jī)指的是

指通過軟件模擬的具有完整硬件系統(tǒng)功能的、運(yùn)行在一個(gè)完全隔離環(huán)境中的完整計(jì)算機(jī)系統(tǒng)。

我們常見的虛擬機(jī)有VM Ware,Virtual Box,JVM
而今天我們要介紹的內(nèi)容是虛擬機(jī)中很重要的一個(gè)概念耳幢,虛擬機(jī)的內(nèi)存結(jié)構(gòu)

2 虛擬機(jī)內(nèi)存結(jié)構(gòu)

JVM內(nèi)存結(jié)構(gòu).jpg

其中最重要的概念是 方法區(qū),JAVA堆睛藻,JAVA棧启上,指令計(jì)數(shù)器(PC)

  1. 指令計(jì)數(shù)器(PC)
    每個(gè)線程都有獨(dú)立的程序計(jì)數(shù)器,各線程的互不影響店印,用于存儲(chǔ)下一條執(zhí)行的虛擬機(jī)指令地址(對(duì)于Native方法則為空undefined)

  2. JAVA棧(VM Stack)
    我們知道是一種先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu)冈在,它有點(diǎn)像機(jī)關(guān)槍的彈夾先被放進(jìn)去的子彈最后被打出來。
    JVM會(huì)為每一個(gè)線程創(chuàng)建一個(gè)棧按摘,JAVA中的棧是以棧幀為基本的數(shù)據(jù)單元,在一個(gè)線程棧里面會(huì)有很多個(gè)棧幀(Frame)包券,每一個(gè)棧幀對(duì)應(yīng)一個(gè)方法。例如:我們一般在main方法寫的程序炫贤,叫做主線程中main方法的棧幀溅固。而這個(gè)main方法的棧幀存儲(chǔ)著,該方法運(yùn)行時(shí)所需要的數(shù)據(jù)兰珍。當(dāng)main方法調(diào)用其他方法例如max()方法发魄。那么max方法所對(duì)應(yīng)的棧幀就會(huì)進(jìn)行壓棧操作,成為當(dāng)前的棧幀。當(dāng)max()方法執(zhí)行結(jié)束之后俩垃,當(dāng)前的棧幀就會(huì)出棧,main方法重新成為當(dāng)前的棧幀汰寓。
    那么一個(gè)棧幀主要存儲(chǔ)著哪些數(shù)據(jù)呢口柳?主要包含下面的數(shù)據(jù)

    • 局部變量表
    • 操作數(shù)棧
    • 方法返回地址
    • 動(dòng)態(tài)鏈接

    2.1 局部變量表:
    局部變量表是一組變量值存儲(chǔ)空間,用于存放方法參數(shù)和方法內(nèi)部定義的局部變量有滑,其中存放的數(shù)據(jù)的類型是編譯期可知的各種基本數(shù)據(jù)類型跃闹、對(duì)象引用(reference)和(returnAddress)類型(它指向了一條字節(jié)碼指令的地址)。局部變量表所需的內(nèi)存空間在編譯期間完成計(jì)算的毛好,即在Java程序被編譯成Class文件時(shí)望艺,就確定了所需分配的最大局部變量表的容量。當(dāng)進(jìn)入一個(gè)方法時(shí)肌访,這個(gè)方法需要在棧中分配多大的局部變量空間是完全確定的找默,在方法運(yùn)行期間不會(huì)改變局部變量表的大小。

    2.2 操作數(shù)棧:
    操作數(shù)棧又常被稱為操作棧吼驶,操作數(shù)棧的最大深度也是在編譯的時(shí)候就確定了惩激。32位數(shù)據(jù)類型所占的棧容量為1, 64位數(shù)據(jù)類型所占的棧容量為2。當(dāng)一個(gè)方法開始執(zhí)行時(shí)蟹演,它的操作棧是空的风钻,在方法的執(zhí)行過程中,會(huì)有各種字節(jié)碼指令(比如:加操作酒请、賦值元算等)向操作棧中寫入和提取內(nèi)容骡技,也就是入棧和出棧操作。Java虛擬機(jī)的解釋執(zhí)行引擎稱為“基于棧的執(zhí)行引擎”羞反,其中所指的“棽茧”就是操作數(shù)棧囤萤。因此我們也稱Java虛擬機(jī)是基于棧的,這點(diǎn)不同于Android虛擬機(jī)喝滞,Android虛擬機(jī)是基于寄存器的阁将。基于棧的指令集最主要的優(yōu)點(diǎn)是可移植性強(qiáng)右遭,主要的缺點(diǎn)是執(zhí)行速度相對(duì)會(huì)慢些做盅;而由于寄存器由硬件直接提供,所以基于寄存器指令集最主要的優(yōu)點(diǎn)是執(zhí)行速度快窘哈,主要的缺點(diǎn)是可移植性差吹榴。

    2.3 動(dòng)態(tài)鏈接:
    每個(gè)棧幀都包含一個(gè)指向運(yùn)行時(shí)常量池(在方法區(qū)中,后面介紹)中該棧幀所屬方法的引用滚婉,持有這個(gè)引用是為了支持方法調(diào)用過程中的動(dòng)態(tài)連接图筹。Class文件的常量池中存在有大量的符號(hào)引用,字節(jié)碼中的方法調(diào)用指令就以常量池中指向方法的符號(hào)引用為參數(shù)让腹。這些符號(hào)引用远剩,一部分會(huì)在類加載階段或第一次使用的時(shí)候轉(zhuǎn)化為直接引用(如 final、static 域等)骇窍,稱為靜態(tài)解析瓜晤,另一部分將在每一次的運(yùn)行期間轉(zhuǎn)化為直接引用,這部分稱為動(dòng)態(tài)連接腹纳。

    2.4 方法返回地址:
    當(dāng)一個(gè)方法被執(zhí)行后痢掠,有兩種方式退出該方法:執(zhí)行引擎遇到了任意一個(gè)方法返回的字節(jié)碼指令或遇到了異常,并且該異常沒有在方法體內(nèi)得到處理嘲恍。無論采用何種退出方式足画,在方法退出之后,都需要返回到方法被調(diào)用的位置佃牛,程序才能繼續(xù)執(zhí)行淹辞。方法返回時(shí)可能需要在棧幀中保存一些信息,用來幫助恢復(fù)它的上層方法的執(zhí)行狀態(tài)俘侠。一般來說桑涎,方法正常退出時(shí),調(diào)用者的PC計(jì)數(shù)器的值就可以作為返回地址兼贡,棧幀中很可能保存了這個(gè)計(jì)數(shù)器值攻冷,而方法異常退出時(shí),返回地址是要通過異常處理器來確定的遍希,棧幀中一般不會(huì)保存這部分信息等曼。方法退出的過程實(shí)際上等同于把當(dāng)前棧幀出站,因此退出時(shí)可能執(zhí)行的操作有:恢復(fù)上層方法的局部變量表和操作數(shù)棧,如果有返回值禁谦,則把它壓入調(diào)用者棧幀的操作數(shù)棧中胁黑,調(diào)整PC計(jì)數(shù)器的值以指向方法調(diào)用指令后面的一條指令。

  1. JAVA堆(Heap)
    所有線程共享的內(nèi)存區(qū)域州泊,用于存放對(duì)象實(shí)例
  2. 方法區(qū)(Method Area)
    線程共享丧蘸,用于存放已加載的類、常量遥皂、靜態(tài)變量力喷、JIT編譯后的代碼等數(shù)據(jù)。
    對(duì)于HotSpot虛擬機(jī)用戶而言演训,經(jīng)常將方法區(qū)稱為永生代(Permanent Generation)弟孟,是因?yàn)镠otSpot虛擬機(jī)用永生代實(shí)現(xiàn)方法區(qū),用GC管理方法區(qū)样悟。
  3. 綜合案例
    綜合例子.jpg
public class Sample {
    private String name;
    public Sample(String name) {
        this.name = name;
    }
    public void printName() {
        System.out.println(name);
    }
}
public class appMain {
    public static void main(String[] args) {
        Sample test1 = new Sample("測(cè)試1");
        Sample test2 = new Sample("測(cè)試2");   
        test1.printName();
        test2.printName();
    }
}

程序的執(zhí)行流程如下拂募。

  1. appMain類信息(即appMain.class對(duì)象)通過類加載器加載進(jìn)方法區(qū)
  2. test1,test2 是自定義類Sample類的兩個(gè)引用窟她,放置在主線程main方法對(duì)應(yīng)的棧幀中陈症。
  3. Sample類的兩個(gè)實(shí)例放置在堆區(qū)中。
  4. 分別調(diào)用在test1,test2,關(guān)于Sample存儲(chǔ)在方法區(qū)中的printName()方法震糖。
  5. 返回main方法爬凑,程序結(jié)束。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末试伙,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子于样,更是在濱河造成了極大的恐慌疏叨,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件穿剖,死亡現(xiàn)場(chǎng)離奇詭異蚤蔓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)糊余,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門秀又,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人贬芥,你說我怎么就攤上這事吐辙。” “怎么了蘸劈?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵昏苏,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng)贤惯,這世上最難降的妖魔是什么洼专? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮孵构,結(jié)果婚禮上屁商,老公的妹妹穿的比我還像新娘。我一直安慰自己颈墅,他們只是感情好蜡镶,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著精盅,像睡著了一般帽哑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叹俏,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天妻枕,我揣著相機(jī)與錄音,去河邊找鬼粘驰。 笑死屡谐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蝌数。 我是一名探鬼主播愕掏,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼顶伞!你這毒婦竟也來了饵撑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤唆貌,失蹤者是張志新(化名)和其女友劉穎滑潘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锨咙,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡语卤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了酪刀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粹舵。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖骂倘,靈堂內(nèi)的尸體忽然破棺而出眼滤,到底是詐尸還是另有隱情,我是刑警寧澤历涝,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布柠偶,位于F島的核電站情妖,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏诱担。R本人自食惡果不足惜毡证,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蔫仙。 院中可真熱鬧料睛,春花似錦、人聲如沸摇邦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽施籍。三九已至居扒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丑慎,已是汗流浹背喜喂。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留竿裂,地道東北人玉吁。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像腻异,于是被迫代替她去往敵國(guó)和親进副。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理悔常,服務(wù)發(fā)現(xiàn)影斑,斷路器,智...
    卡卡羅2017閱讀 134,637評(píng)論 18 139
  • 3.鄴城春秋 在袁紹死后袁紹集團(tuán)的內(nèi)部政治紛爭(zhēng)當(dāng)中机打,冀州豪強(qiáng)被削弱矫户。在曹操?gòu)氐紫麥缭B集團(tuán)之后,取得了冀州這樣一個(gè)...
    張七公子閱讀 1,022評(píng)論 0 13
  • 最近在接 spring cloug hystrix 熔斷姐帚,了解一下熔斷的基本概念和原理。此篇原文是馬丁花的文章 h...
    holysu閱讀 4,330評(píng)論 3 3
  • 我不是藝術(shù)家障涯,也不是詩人罐旗,我只是在刻畫痛苦。 千百年來的陰影魔障唯蝶,交織著差別甚小的憂郁九秀。 我點(diǎn)燃火焰,將自己燃燒在...
    陳高興_閱讀 1,357評(píng)論 1 11