運(yùn)行時數(shù)據(jù)區(qū)域
運(yùn)行時數(shù)據(jù)區(qū)域主要分為:堆桃漾,棧坏匪,方法區(qū),程序計數(shù)器撬统。實(shí)際上适滓,我們所說的棧又分為:java虛擬機(jī)棧,本地方法棧恋追。
1. 程序計數(shù)器
-
概念
程序計數(shù)器就是當(dāng)前線程執(zhí)行字節(jié)碼的行號指示器凭迹。(這里我們看java虛擬機(jī)的時候,不再考慮程序或者我們寫的java代碼苦囱,而是 字節(jié)碼)嗅绸。。
-
特征
為了線程切換后能回到正確的位置撕彤,因此每一個線程都有一個程序計數(shù)器朽砰,這樣子程序計數(shù)器各自互不影響,是線程私有內(nèi)存喉刘。
內(nèi)存區(qū)域里唯一一個不會出現(xiàn)內(nèi)存泄露和內(nèi)存溢出問題的區(qū)域。
當(dāng)執(zhí)行執(zhí)行的是本地方法時漆弄,程序計數(shù)器指向空(undifined)睦裳,否則,程序計數(shù)器正常指向撼唾。
2.java虛擬機(jī)棧
-
概念
java虛擬機(jī)棧描述的是java方法執(zhí)行的內(nèi)存模型廉邑,存儲的是棧幀。當(dāng)一個方法被調(diào)用倒谷,表示棧幀入棧蛛蒙,當(dāng)方法調(diào)用完畢返回時,表示棧幀出棧渤愁。那么棧幀是什么呢牵祟?
-
什么是棧幀?
棧幀可以理解為一個方法的運(yùn)行空間抖格,主要包括四部分:變量表诺苹,操作數(shù)棧,動態(tài)鏈接雹拄,返回地址(方法出口)
如圖所示:
java虛擬機(jī)棧.png -
?
其中:
? **frame**表示棧幀收奔。隨著方法的調(diào)用而入棧,調(diào)用結(jié)束或者返回異常而出棧滓玖。
? **local variables**表示局部變量表坪哄,是一個具有物理地址連續(xù)的內(nèi)存空間,最小單位是Slot。用來存放方法參數(shù)和方法內(nèi)部定義的局部變量翩肌。虛擬機(jī)沒有明確指明一個Slot的內(nèi)存空間大小模暗。但是boolean、byte摧阅、char汰蓉、short、int棒卷、float顾孽、reference、returnAddress類型的數(shù)據(jù)都可以用32位空間或更小的內(nèi)存來存放比规。這些類型占用一個Slot若厚。Java中的long和double類型是64位,占用兩個Slot蜒什。Slot的空間是可以復(fù)用的测秸,當(dāng)pc計數(shù)器的值已經(jīng)超出了某個變量的作用域時,下一個變量不必使用新的Slot空間灾常,可以去覆蓋前面那個空間
? **operand stack**操作數(shù)棧霎冯,當(dāng)一個方法剛剛開始的時候,這個方法的操作數(shù)棧是空的钞瀑,在方法的執(zhí)行過程中沈撞,會有各種字節(jié)碼指令往操作數(shù)棧中寫入和提取內(nèi)容,也就是入棧和出棧操作.
? **動態(tài)鏈接**雕什,一個方法A調(diào)用另一個方法B缠俺,或者一個類使用另一個類的成員變量時,總得知道被調(diào)用者的名字吧贷岸?在Class文件中的常量池中存有大量的符號引用壹士,而被調(diào)用者有個這樣的符號引用叫做BB,那么在運(yùn)行期字節(jié)碼獲取到的是BB偿警,然后直接將BB轉(zhuǎn)為方法B來調(diào)用躏救,這個在運(yùn)行期將符號應(yīng)用轉(zhuǎn)化為直接引用成為動態(tài)鏈接。
? **return value**螟蒸,返回值落剪。如果方法正常結(jié)束調(diào)用,則返回方法定義的返回值尿庐。如果是異常結(jié)束調(diào)用忠怖,則不會返回方法值給調(diào)用者。
-
特征
當(dāng)進(jìn)入一個調(diào)用方法時抄瑟,局部變量表在編譯期間已完成分配凡泣,在運(yùn)行期間不會變更大小了枉疼。
(StackOverflowError):當(dāng)當(dāng)前線程申請的java虛擬機(jī)棧空間大于允許的java虛擬機(jī)棧大小時鞋拟,會拋出StackOverflowError骂维。一般而言,java虛擬機(jī)中贺纲,-Xss 設(shè)置棧的大小航闺,棧的大小直接決定函數(shù)調(diào)用的可達(dá)深度
(OutOfMemoryError):如果java虛擬機(jī)是允許可動態(tài)擴(kuò)展的,當(dāng)擴(kuò)展時無法申請到足夠內(nèi)存猴誊,會拋出OutOfMemoryError異常潦刃。
3.本地方發(fā)棧
-
概念
本地方發(fā)棧和java虛擬機(jī)棧功能十分相似,區(qū)別是java虛擬機(jī)棧是對java方法服務(wù)懈叹,而本地方發(fā)棧是對本地方法(native)方法服務(wù)乖杠。
-
特征
也會拋出(StackOverflowError)和(OutOfMemoryError)
4.java堆
-
概念
java虛擬機(jī)管理的最大的一塊內(nèi)存區(qū)域,是存放java對象的一塊被所有線程共享的區(qū)域澄成。
-
特征
如果堆中沒有足夠內(nèi)存用來儲存對象胧洒,并且堆也無法再擴(kuò)展時,則會發(fā)生(OutOfMemoryError)
垃圾回收器主要管理的區(qū)域
粗分為:新生代和老年代墨状。細(xì)分為:Eden空間,From survivor空間卫漫,to survivor空間。
5.方法區(qū)
-
概念
方法區(qū)和java堆一樣肾砂,是線程共享的汛兜,主要存放:已被虛擬機(jī)加載的類信息,常量通今,靜態(tài)常量,即時編譯器編譯后的代碼等數(shù)據(jù)肛根,比如class中一些類的版本辫塌,等信息。
-
特征
可以實(shí)現(xiàn)垃圾收集派哲,也可實(shí)現(xiàn)垃圾收集臼氨。如果實(shí)現(xiàn)垃圾收集主要針對常量池的回收和類型的卸載。
方法區(qū)無法滿足內(nèi)存分配時芭届,拋出(OutOfMemoryError)
常量池是方法區(qū)的一部分储矩,用于存放字面量和符號引用。在編譯時褂乍,java類并不知道所引用的類的實(shí)際地址持隧,因此只能使用符號引用來代替,這些都放在常量池中逃片。具備動態(tài)性屡拨,就是說并不只有在編譯器將字面量等信息放入到常量池,也可以在運(yùn)行期間有新增的字面量數(shù)據(jù)也可以存儲在常量池中。java運(yùn)用的比較多的是String.intern()方法呀狼。常量池也是方法區(qū)的一部分裂允,也會拋出(OutOfMemoryError)。