JVM虛擬機詳解
程序計數(shù)器
內(nèi)存空間小,線程私有。字節(jié)碼解釋器工作是就是通過改變這個計數(shù)器的值來選取下一條需要執(zhí)行指令的字節(jié)碼指令,分支、循環(huán)、跳轉(zhuǎn)、異常處理、線程恢復等基礎(chǔ)功能都需要依賴計數(shù)器完成??偠灾?,程序計數(shù)器是為線程間跳轉(zhuǎn)服務的。
如果線程正在執(zhí)行一個 Java 方法,這個計數(shù)器記錄的是正在執(zhí)行的虛擬機字節(jié)碼指令的地址;如果正在執(zhí)行的是 Native 方法,這個計數(shù)器的值則為 (Undefined)。此內(nèi)存區(qū)域是唯一一個在 Java 虛擬機規(guī)范中沒有規(guī)定任何 OutOfMemoryError 情況的區(qū)域。
Java虛擬機棧
線程私有,生命周期和線程一致。描述的是 Java 方法執(zhí)行的內(nèi)存模型:每個方法在執(zhí)行時都會床創(chuàng)建一個棧幀(Stack Frame)用于存儲局部變量表、操作數(shù)棧、動態(tài)鏈接、方法出口等信息。每一個方法從調(diào)用直至執(zhí)行結(jié)束,就對應著一個棧幀從虛擬機棧中入棧到出棧的過程。
局部變量表:存放了編譯期可知的八種基本類型、對象引用(reference 類型)和 returnAddress 類型(指向了一條字節(jié)碼指令的地址)。
Java虛擬機??赡艹霈F(xiàn)兩種類型的異常:線程請求的棧深度大于虛擬機允許的棧深度,將拋出StackOverflowError。虛擬機??臻g可以動態(tài)擴展,當動態(tài)擴展是無法申請到足夠的空間時,拋出OutOfMemory異常。
本地方法棧
它是為本地方法服務的,而本地方法棧則為虛擬機使用到的 Native 方法服務, jdk版本不同,本地方法??赡懿煌行┨厥獍姹景褩:捅镜胤椒6弦?。也會有 StackOverflowError 和 OutOfMemoryError 異常。
堆
jvm內(nèi)存只有一個堆,所有線程共享這個堆,幾乎所有的對象都存放在堆里。堆是內(nèi)存空間最大的一塊,相對的運行速度是最慢的。垃圾回收指的就是回收堆里的內(nèi)存垃圾,所有 new的象都會在堆里。
垃圾回收機制和堆,為什么堆里會有垃圾 ?
當你創(chuàng)建一個對象,這個對象使用完畢之后就是垃圾,當一個對象沒有任何一個地址可以指向它的時候,它就是不可達的對象。
jvm 垃圾回收機制回收的就是不可達的對象,目前 jvm 垃圾回收機制用的是科學分析法 ,它會遍歷堆里的對象,然后檢測是否有地址可達這個對象,如果不可達那么就回收。注意:堆是不連續(xù)的空間。
方法區(qū)
方法區(qū)有兩種說法:
1. 被認為是 堆得一部分 負責一部分特殊用途。
2. 和堆是不同概念 也不是一體的。
方法區(qū)主要分為三塊:
1.靜態(tài)區(qū),靜態(tài)的東西都存儲在這個地方。
2.類信息區(qū),字節(jié)碼被加載到內(nèi)存里 存儲在類信息區(qū)。
3.常量池,所有的常量存儲在常量池里。
什么是常量池 ?
常量池里存儲的都是常量,有些類實現(xiàn)了常量池技術(shù),常量是為了減少常見的對象的創(chuàng)建。
什么是常量池技術(shù) ?以 字符串為例:String是不可變的字符串,也就是說 String類的對象本身是不變的,是一個常量在你 String str = "大數(shù)據(jù)" 時。會首先到常量池中尋找,查看是否有 "大數(shù)據(jù)" 這個字符串對象。
如果有,把該對象的地址給與 str存儲,以后再有變量被賦值為 "大數(shù)據(jù)"時都會如此操作;如果沒有,那么就把 "哈大數(shù)據(jù)" 對象創(chuàng)建存入常量池,然后地址為str。
注意 :String類實現(xiàn)常量池在顯示賦值時支持常量池技術(shù),在new對象時不支持。
聯(lián)系客服