Java Memory Model ,JMM Java內(nèi)存模型
(圖片來源于網(wǎng)絡(luò)缘薛,侵刪酝枢。)
- 程序計(jì)數(shù)器
- Java虛擬機(jī)棧
- 本地方法棧
- 堆
- 方法區(qū)
程序計(jì)數(shù)器涣达,Java虛擬機(jī)棧吐葵,本地方法棧是線程私有的污筷。
方法區(qū)工闺,堆是線程共享的。
- 程序計(jì)數(shù)器
這塊區(qū)域是虛擬機(jī)規(guī)范中唯一沒有OutOfMemory錯(cuò)誤的區(qū)域
- Java虛擬機(jī)棧
描述的是Java方法執(zhí)行的內(nèi)存模型:每個(gè)方法執(zhí)行的同時(shí)會(huì)創(chuàng)建一個(gè)棧幀。
棧幀存儲(chǔ)了方法的局部變量表陆蟆、操作數(shù)棧雷厂、動(dòng)態(tài)連接和方法返回地址等信息。
1)線程請(qǐng)求的棧深度大于虛擬機(jī)允許的棧深度叠殷,將拋出StackOverflowError
2)虛擬機(jī)椄啮辏空間可以動(dòng)態(tài)擴(kuò)展,當(dāng)動(dòng)態(tài)擴(kuò)展無法申請(qǐng)到足夠的空間時(shí)林束,則拋出OutOfMemory異常
本地方法棧
本地方法棧與虛擬機(jī)棧發(fā)揮的作用十分相似像棘,區(qū)別是虛擬機(jī)棧執(zhí)行的是Java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則為虛擬機(jī)使用到的native方法服務(wù)壶冒,可能底層調(diào)用的c或者c++,我們打開jdk安裝目錄可以看到也有很多用c編寫的文件缕题,可能就是native方法所調(diào)用的c代碼。堆
堆是java虛擬機(jī)管理內(nèi)存最大的一塊內(nèi)存區(qū)域依痊,因?yàn)槎汛娣诺膶?duì)象是線程共享的避除,所以多線程的時(shí)候也需要同步機(jī)制
它是所有線程共享的,它的目的是存放對(duì)象實(shí)例胸嘁。同時(shí)它也是GC所管理的主要區(qū)域瓶摆,因此常被稱為GC堆。當(dāng)前主流的虛擬機(jī)如HotPot都能按擴(kuò)展實(shí)現(xiàn)(通過設(shè)置 -Xmx和-Xms)性宏。
如果堆中沒有內(nèi)存內(nèi)存完成實(shí)例分配群井,而且堆無法擴(kuò)展將報(bào)OOM錯(cuò)誤(OutOfMemoryError)
- 方法區(qū)
用于存儲(chǔ)已被虛擬機(jī)加載的類信息、常量毫胜、靜態(tài)變量书斜,如static修飾的變量加載類的時(shí)候就被加載到方法區(qū)中。
運(yùn)行時(shí)常量池
是方法區(qū)的一部分酵使,class文件除了有類的字段荐吉、接口、方法等描述信息之外口渔,還有常量池用于存放編譯期間生成的各種字面量和符號(hào)引用样屠。
溢出的兩個(gè)基本例子:
public class MemErrorTest {
public static void hi(){
hi();
}
public static void main(String[] args) {
try{
List<Object> list = new ArrayList<Object>();
for(;;){
//創(chuàng)建對(duì)象速度可能高于JVM
list.add(new Object());
}
}catch (OutOfMemoryError e){
e.printStackTrace();
}
try{
//遞歸造成StackOverflowError 這邊因?yàn)槊窟\(yùn)行一個(gè)方法將創(chuàng)建一個(gè)棧幀
hi();
}catch (StackOverflowError e){
e.printStackTrace();
}
}
}
運(yùn)行結(jié)果:
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:265)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
at java.util.ArrayList.add(ArrayList.java:462)
at menerror.MemErrorTest.main(MemErrorTest.java:24)
java.lang.StackOverflowError
at menerror.MemErrorTest.hi(MemErrorTest.java:16)
at menerror.MemErrorTest.hi(MemErrorTest.java:16)
at menerror.MemErrorTest.hi(MemErrorTest.java:16)
……