JVM 內(nèi)存模型
共享
實(shí)例域雏节、靜態(tài)域和數(shù)組元素存儲在堆內(nèi)存中趋惨,堆內(nèi)存在線程之間共享(本文使用“共享變量”這個術(shù)語代指實(shí)例域,靜態(tài)域和數(shù)組元素)榜轿。
不共享
局部變量(Local variables),方法定義參數(shù)(java語言規(guī)范稱之為formal method parameters)和異常處理器參數(shù)(exception handler parameters)不會在線程之間共享朵锣,它們不會有內(nèi)存可見性問題谬盐,也不受內(nèi)存模型的影響。
程序計數(shù)器
線程私有
當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器诚些,如果線程正在執(zhí)行的是一個Java 方法飞傀,這個計數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址;如果正在執(zhí)行的是Natvie 方法诬烹,這個計數(shù)器值則為空(Undefined)砸烦。
虛擬機(jī)棧
線程私有
這些幀里面存放的是方法的局部變量,操作數(shù)棧绞吁,動態(tài)鏈接幢痘,方法返回地址和一些額外的附加信息組成。每一個方法被調(diào)用直至執(zhí)行完成的過程家破,就對應(yīng)著一個棧幀在虛擬機(jī)棧中從入棧到出棧的過程颜说。
局部變量表
系統(tǒng)不會為局部變量賦予初始值(實(shí)例變量和類變量都會被賦予初始值)。也就是說不存在類變量那樣的準(zhǔn)備階段汰聋。
操作數(shù)棧
虛擬機(jī)把操作數(shù)棧作為它的工作區(qū)——大多數(shù)指令都要從這里彈出數(shù)據(jù)门粪,執(zhí)行運(yùn)算,然后把結(jié)果壓回操作數(shù)棧烹困。比如庄拇,iadd指令就要從操作數(shù)棧中彈出兩個整數(shù),執(zhí)行加法運(yùn)算韭邓,其結(jié)果又壓回到操作數(shù)棧
動態(tài)連接
如果符號引用是在類加載階段或者第一次使用的時候轉(zhuǎn)化為直接應(yīng)用措近,那么這種轉(zhuǎn)換成為靜態(tài)解析,如果是在運(yùn)行期間轉(zhuǎn)換為直接引用女淑,那么這種轉(zhuǎn)換就成為動態(tài)連接瞭郑。
返回地址
本地方法棧
與虛擬機(jī)棧所發(fā)揮的作用是非常相似的,其區(qū)別不過是虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java 方法(也就是字節(jié)碼)服務(wù)鸭你,而本地方法棧則是為虛擬機(jī)使用到的Native 方法服務(wù)屈张。
堆
線程共享
Java 堆是被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機(jī)啟動時創(chuàng)建袱巨。此內(nèi)存區(qū)域的唯一目的就是存放對象實(shí)例
方法區(qū)
線程共享
方法區(qū)用來存儲類型的元數(shù)據(jù)信息阁谆,一個.class文件是類被java虛擬機(jī)使用之前的表現(xiàn)形式,一旦這個類要被使用愉老,java虛擬機(jī)就會對其進(jìn)行裝載场绿、連接(驗(yàn)證、準(zhǔn)備嫉入、解析)和初始化焰盗。而裝載后的結(jié)果就是由.class文件轉(zhuǎn)變?yōu)榉椒▍^(qū)中的一段特定的數(shù)據(jù)結(jié)構(gòu)璧尸。
包括:類中聲明的靜態(tài)變量
- 訪問方法區(qū)必須注意線程安全
- 方法區(qū)的大小不必是固定的
- 方法區(qū)也可被垃圾收集,當(dāng)某個類不在被使用(不可觸及)時熬拒,JVM將卸載這個類爷光,進(jìn)行垃圾收集
運(yùn)行時常量池
存放字面量及符號引用,方法區(qū)的一部分澎粟,具有動態(tài)性
直接內(nèi)存
可以使用Native 函數(shù)庫直接分配堆外內(nèi)存
堆與棧的對比
堆和棧都是內(nèi)存中的一部分
在函數(shù)中定義的一些基本類型的變量和對象的引用變量都在函數(shù)的棧內(nèi)存中分配蛀序。 當(dāng)在一段代碼塊定義一個變量時,Java就在棧中為這個變量分配內(nèi)存空間活烙,當(dāng)超過變量的作用域后哼拔,Java會自動釋放掉為該變量所分配的內(nèi)存空間,該內(nèi)存空間可以立即被另作他用瓣颅。
堆內(nèi)存用來存放由new創(chuàng)建的對象和數(shù)組倦逐。
在堆中分配的內(nèi)存,由Java虛擬機(jī)的自動垃圾回收器來管理宫补。
在堆中產(chǎn)生了一個數(shù)組或?qū)ο蠛竺世眩€可以在棧中定義一個特殊的變量,讓棧中這個變量的取值等于數(shù)組或?qū)ο笤诙褍?nèi)存中的首地址粉怕,棧中的這個變量就成了數(shù)組或?qū)ο蟮囊米兞俊?br>
引用變量就相當(dāng)于是為數(shù)組或?qū)ο笃鸬囊粋€名稱健民,以后就可以在程序中使用棧中的引用變量來訪問堆中的數(shù)組或?qū)ο蟆?/p>