java痴和堆_JAVA虚拟机理解 - 爱笑的痴迷者的个人空间 - OSCHINA - 中文开源技术交流社区...
JVM定義:
JVM(Java Virtual Machine),是一種運(yùn)行Java程序的軟件實(shí)現(xiàn),是虛擬的機(jī)器。Java程序與平臺(tái)無(wú)關(guān),它直接在虛擬機(jī)中運(yùn)行。
JVM運(yùn)行過(guò)程:
JVM將內(nèi)存分劃如下五個(gè)區(qū)域:
1、方法區(qū);2、堆區(qū);3、虛擬機(jī)棧;4、本地方法棧;5、程序計(jì)數(shù)器;
方法區(qū)(Method Area):
JVM使用類(lèi)裝載器裝載某個(gè)類(lèi)時(shí),會(huì)找到相應(yīng)的class文件,并讀取該文件內(nèi)容信息,以及將存儲(chǔ)到方法,最后返回一個(gè)class實(shí)例。
方法區(qū)存放內(nèi)容:1、類(lèi)的全限定名(類(lèi)的全路徑名);2、類(lèi)的直接超類(lèi)的權(quán)全限定名(如果這個(gè)類(lèi)是Object,則它沒(méi)有超類(lèi));3、類(lèi)的類(lèi)型(類(lèi)或接口);4、類(lèi)的訪(fǎng)問(wèn)修飾符,public,abstract,final等;5、類(lèi)的直接接口全限定名的有序列表;6、常量池(字段,方法信息,靜態(tài)變量,類(lèi)型引用(class))等;
方法區(qū)是全局共享的,但是它也是線(xiàn)程安全的。在一定條件下它也會(huì)被GC。當(dāng)方法區(qū)使用的內(nèi)存超過(guò)它允許的大小時(shí),就會(huì)拋出OutOfMemory:PermGen Space異常。產(chǎn)生該錯(cuò)誤的原因大都出于以下原因:JVM內(nèi)存過(guò)小、程序不嚴(yán)密,產(chǎn)生了過(guò)多的垃圾。
JVM方法區(qū)的相關(guān)參數(shù),最小值:--XX:PermSize;最大值:--XX:MaxPermSize。
堆區(qū)(Heap?Area):
一個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū),類(lèi)的實(shí)例(new創(chuàng)造的對(duì)象)從中分配空間,它的管理是由垃圾回收來(lái)負(fù)責(zé)的。堆區(qū)由所有線(xiàn)程共享,且用來(lái)存儲(chǔ)對(duì)象實(shí)例及數(shù)組值。
對(duì)于堆區(qū)大小,可以通過(guò)參數(shù)-Xms和-Xmx來(lái)控制:
-Xms為JVM啟動(dòng)時(shí)申請(qǐng)的最新head內(nèi)存,默認(rèn)為物理內(nèi)存的1/64但小于1GB;
-Xmx為JVM可申請(qǐng)的最大Head內(nèi)存,默認(rèn)為物理內(nèi)存的1/4但小于1GB;
當(dāng)剩余堆空間小于40%時(shí),JVM會(huì)增大Head到-Xmx大小,可通過(guò)-XX:MinHeapFreeRadio參數(shù)來(lái)控制這個(gè)比例;
當(dāng)空余堆內(nèi)存大于70%時(shí),JVM會(huì)減少Head大小到-Xms指定大小,可通過(guò)-XX:MaxHeapFreeRatio來(lái)指定這個(gè)比例。
虛擬機(jī)棧(JVM Stacks):
虛擬機(jī)棧是線(xiàn)程私有的,它的生命周期與線(xiàn)程相同。虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模式:每個(gè)方法在執(zhí)行的同時(shí)都會(huì)創(chuàng)建一個(gè)棧幀(Statck Frame),用于存儲(chǔ)局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口等信息。每個(gè)方法從調(diào)用至執(zhí)行完成的過(guò)程,就對(duì)應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中入棧到出棧的過(guò)程。
局部變量表存放了編譯期可知的各種基本數(shù)據(jù)類(lèi)型(boolean、btye、char、short、int、float、long、double)、對(duì)象引用(reference類(lèi)型,它不等于對(duì)象本身,可能是一個(gè)指向?qū)ο笃鹗嫉刂返囊弥羔?#xff0c;也可能是指向一個(gè)代表對(duì)象的句柄或其他與此對(duì)象相關(guān)的位置)和returnAddress類(lèi)型(指向了一個(gè)字節(jié)碼指令的地址)
其中64位長(zhǎng)度的long和double類(lèi)型的數(shù)據(jù)會(huì)占用2個(gè)局部變量空間(Slot),其他都是1個(gè)Slot。局部變量表所需的內(nèi)存空間是在編譯期間完成分配,當(dāng)進(jìn)入一個(gè)方法時(shí),這個(gè)方法需要在幀中分配多大的局部變量空間是完全確定的,在方法運(yùn)行期間不會(huì)改變局部變量表的大小。
虛擬機(jī)棧中定義了兩種異常,如果線(xiàn)程請(qǐng)求的棧深度大于虛擬機(jī)所允許深度,則拋出StatckOverFlowError(棧溢出);不過(guò)多數(shù)Java虛擬機(jī)都允許動(dòng)態(tài)擴(kuò)展虛擬機(jī)棧的大小(有少部分是固定長(zhǎng)度的),所以線(xiàn)程可以一直申請(qǐng)棧,直到內(nèi)存不足,則會(huì)拋出OutOfMemoryError(內(nèi)存溢出)。
本地方法棧(Native Method Stack):
本地方法棧用于支持native方法的執(zhí)行,存儲(chǔ)了每個(gè)native方法調(diào)用的狀態(tài)。本地方法棧和虛擬機(jī)方法棧運(yùn)行機(jī)制一致,它們唯一的區(qū)別就是,虛擬機(jī)棧是執(zhí)行Java方法的,而本地方法棧是用來(lái)執(zhí)行native方法的,在很多虛擬機(jī)中,會(huì)將本地方法棧與虛擬機(jī)棧放在一起使用。
程序計(jì)數(shù)器(Program Counter Register):
一個(gè)比較小的內(nèi)存空間,可以看作是當(dāng)前線(xiàn)程所執(zhí)行的字節(jié)碼的行號(hào)指示器。在虛擬機(jī)的概念模型里(僅是概念模型,各種虛擬機(jī)可能會(huì)通過(guò)一些更高效的方式去實(shí)現(xiàn)),字節(jié)碼解釋器工作時(shí),會(huì)通過(guò)改變這個(gè)計(jì)數(shù)器的值來(lái)選取下一條需要執(zhí)行的字節(jié)碼指令,分支、循環(huán)、跳轉(zhuǎn)、異常處理、線(xiàn)程恢復(fù)等基礎(chǔ)功能都需要依賴(lài)這個(gè)計(jì)數(shù)器來(lái)完成。
由于Java虛擬機(jī)的多線(xiàn)程是通過(guò)線(xiàn)程輪流切換并分配處理器執(zhí)行時(shí)間的方式來(lái)實(shí)現(xiàn)的,在任何一個(gè)確定的時(shí)刻,一個(gè)處理器(對(duì)于多核處理器來(lái)說(shuō)是一個(gè)內(nèi)核)都只會(huì)執(zhí)行一個(gè)線(xiàn)程中的指令。因此,為了線(xiàn)程切換后能恢復(fù)到正確的執(zhí)行位置,每條線(xiàn)程都需要有一個(gè)獨(dú)立的程序計(jì)數(shù)器,每條線(xiàn)程之間計(jì)數(shù)器互不影響,獨(dú)立存儲(chǔ)。
如果線(xiàn)程正在執(zhí)行的是一個(gè)Java方法,這個(gè)計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令地址;如果正在執(zhí)行的是Native方法,這個(gè)計(jì)數(shù)器的值為空(Undefined)。此內(nèi)存區(qū)域是唯一一個(gè)在Java虛擬機(jī)規(guī)范中沒(méi)有任何OutOfMemoryError的區(qū)域。
JAVA對(duì)象訪(fǎng)問(wèn)方式
一個(gè)Java的引用訪(fǎng)問(wèn)涉及到3個(gè)內(nèi)存區(qū)域:JVM棧、堆、方法區(qū)。
以最簡(jiǎn)單的本地變量引用,Object obj = new Object()為例:
類(lèi)變量(方法區(qū)):獨(dú)立于方法之外的變量,用 static 修飾;
實(shí)例變量(堆):獨(dú)立于方法之外的變量,不過(guò)沒(méi)有 static 修飾;
局部變量(棧):類(lèi)的方法中的變量;
public class Test{
static int a=0; // 類(lèi)變量
String b="hello world"; // 實(shí)例變量
public void method(){
int c =0; // 局部變量
}
}
Object obj表示一個(gè)本地引用,存儲(chǔ)在JVM棧的本地變量表中,表示一個(gè)reference類(lèi)型數(shù)據(jù);
new Object()作為實(shí)例對(duì)象數(shù)據(jù)存儲(chǔ)在堆中;
堆中還記錄了能夠查詢(xún)到此Object對(duì)象的類(lèi)型數(shù)據(jù)(接口、方法、field、對(duì)象類(lèi)型等)的地址,實(shí)際的數(shù)據(jù)則存儲(chǔ)在方法區(qū)中;
在Java虛擬機(jī)規(guī)范中,只規(guī)定了指向?qū)ο蟮囊?#xff0c;對(duì)于通過(guò)reference類(lèi)型引用訪(fǎng)問(wèn)具體對(duì)象的方式并未做規(guī)定,不過(guò)目前主流的實(shí)現(xiàn)方式只要有兩種:
1)、句柄訪(fǎng)問(wèn):通過(guò)句柄訪(fǎng)問(wèn)的實(shí)現(xiàn)方式中,JVM堆中會(huì)劃分單獨(dú)一塊內(nèi)存區(qū)域作為句柄池,句柄池中存儲(chǔ)了對(duì)象實(shí)例數(shù)據(jù)(在堆中)和對(duì)象類(lèi)型數(shù)據(jù)(在方法區(qū)中)的指針。這種實(shí)現(xiàn)方法由于用句柄表示地址,因此十分穩(wěn)定。
2)、指針訪(fǎng)問(wèn):通過(guò)直接指針訪(fǎng)問(wèn)的方式中,reference中存儲(chǔ)的就是對(duì)象在堆中的實(shí)際地址,在堆中存儲(chǔ)的對(duì)象信息中包含了在方法區(qū)中的相應(yīng)類(lèi)型數(shù)據(jù)。這種方法最大的優(yōu)勢(shì)是速度快,在HotSpot虛擬機(jī)中用的就是這種方式。
總結(jié)
以上是生活随笔為你收集整理的java痴和堆_JAVA虚拟机理解 - 爱笑的痴迷者的个人空间 - OSCHINA - 中文开源技术交流社区...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: CUDA: GPU高性能运算
- 下一篇: C与CUDA混合编程的配置问题