Java虛擬機(jī)在執(zhí)行Java程序的過程中猫十,會(huì)把它所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)然爆。這些區(qū)域有各自的用途,以及創(chuàng)建和銷毀的時(shí)間浦妄,有的區(qū)域隨著虛擬機(jī)進(jìn)程的啟動(dòng)而存在,有的區(qū)域則依賴用戶線程的啟動(dòng)和結(jié)束而建立和銷毀见芹,我們可以將這些區(qū)域統(tǒng)稱為Java運(yùn)行時(shí)數(shù)據(jù)區(qū)域剂娄。
如下圖是一個(gè)內(nèi)存模型的關(guān)系圖(詳情見圖:內(nèi)存劃分.png):
如上圖所示,Java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)域被分為五個(gè)區(qū)域:堆(Heap)玄呛、棧(Stack)阅懦、本地方法棧(Native Stack)、方法區(qū)(Method Area)徘铝、程序計(jì)數(shù)器(Program Count Register)耳胎。
1. 堆(Heap)
對(duì)于大多數(shù)應(yīng)用來說,Java Heap是Java虛擬機(jī)管理的內(nèi)存的最大一塊惕它,這塊區(qū)域隨著虛擬機(jī)的啟動(dòng)而創(chuàng)建怕午。在實(shí)際的運(yùn)用中,我們創(chuàng)建的對(duì)象和數(shù)組就是存放在堆里面淹魄。如果你聽說線程安全的問題郁惜,就會(huì)很明確的知道Java Heap是一塊共享的區(qū)域,操作共享區(qū)域的成員就有了鎖和同步甲锡。
與Java Heap相關(guān)的還有Java的垃圾回收機(jī)制(GC),Java Heap是垃圾回收器管理的主要區(qū)域兆蕉。程序猿所熟悉的新生代、老生代缤沦、永久代的概念就是在堆里面虎韵,現(xiàn)在大多數(shù)的GC基本都采用了分代收集算法。如果再細(xì)致一點(diǎn)缸废,Java Heap還有Eden空間包蓝,F(xiàn)rom Survivor空間,To Survivor空間等。
Java Heap可以處于物理上不連續(xù)的內(nèi)存空間中,只要邏輯上是連續(xù)的即可养晋。
2. 棧(Stack)
相對(duì)于Java Heap來講,Java Stack是線程私有的梁钾,她的生命周期與線程相同绳泉。Java Stack描述的是Java方法執(zhí)行時(shí)的內(nèi)存模型,每個(gè)方法執(zhí)行時(shí)都會(huì)創(chuàng)建一個(gè)棧幀(Stack Frame)用語存儲(chǔ)局部變量表姆泻、操作數(shù)棧零酪、動(dòng)態(tài)鏈接、方法出口等信息拇勃。從下圖從可以看到四苇,每個(gè)線程在執(zhí)行一個(gè)方法時(shí),都意味著有一個(gè)棧幀在當(dāng)前線程對(duì)應(yīng)的棧幀中入棧和出棧方咆。
圖中可以看到每一個(gè)棧幀中都有局部變量表月腋。局部變量表存放了編譯期間的各種基本數(shù)據(jù)類型,對(duì)象引用等信息瓣赂。
3. 本地方法棧(Native Stack)
本地方法棧(Native Stack)與Java虛擬機(jī)站(Java Stack)所發(fā)揮的作用非常相似榆骚,他們之間的區(qū)別在于虛擬機(jī)棧為虛擬機(jī)棧執(zhí)行java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則為使用到Native方法服務(wù)煌集。
4. 方法區(qū)(Method Area)
方法區(qū)(Method Area)與堆(Java Heap)一樣妓肢,是各個(gè)線程共享的內(nèi)存區(qū)域,它用于存儲(chǔ)虛擬機(jī)加載的類信息苫纤,常量碉钠,靜態(tài)變量,即時(shí)編譯器編譯后的代碼等數(shù)據(jù)卷拘。雖然Java虛擬機(jī)規(guī)范把方法區(qū)描述為堆的一個(gè)邏輯部分喊废,但是她卻有一個(gè)別名叫做非堆(Non-Heap)。分析下Java虛擬機(jī)規(guī)范恭金,之所以把方法區(qū)描述為堆的一個(gè)邏輯部分操禀,應(yīng)該覺得她們都是存儲(chǔ)數(shù)據(jù)的角度出發(fā)的。一個(gè)存儲(chǔ)對(duì)象數(shù)據(jù)(堆)横腿,一個(gè)存儲(chǔ)靜態(tài)信息(方法區(qū))颓屑。
在上文中,我們看到堆中有新生代耿焊、老生代揪惦、永久代的描述。為什么我們將新生代罗侯、老生代器腋、永久代三個(gè)概念一起說,那是因?yàn)镠otSpot虛擬機(jī)的設(shè)計(jì)團(tuán)隊(duì)選擇把GC分代收集擴(kuò)展至方法區(qū),或者說使用永久代來實(shí)現(xiàn)方法區(qū)而已纫塌。這樣HotSpot的垃圾收集器就能想管理Java堆一樣管理這部分內(nèi)存诊县。簡(jiǎn)單點(diǎn)說就是HotSpot虛擬機(jī)中內(nèi)存模型的分代,其中新生代和老生代在堆中措左,永久代使用方法區(qū)實(shí)現(xiàn)依痊。根據(jù)官方發(fā)布的路線圖信息,現(xiàn)在也有放棄永久代并逐步采用Native Memory來實(shí)現(xiàn)方法區(qū)的規(guī)劃怎披,在JDK1.7的HotSpot中胸嘁,已經(jīng)把原本放在永久代的字符串常量池移出。
5. 總結(jié)
1 凉逛、線程私有的數(shù)據(jù)區(qū)域有:
Java虛擬機(jī)棧(Java Stack)
本地方法棧(Native Stack)
2性宏、 線程共有的數(shù)據(jù)區(qū)域有:
堆(Java Heap)
方法區(qū)