Java的內(nèi)存區(qū)域與內(nèi)存溢出異常你了解嗎
1. 運(yùn)行時(shí)數(shù)據(jù)區(qū)域

1. 程序計(jì)數(shù)器(線程私有)
當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器,分支、循環(huán)、跳轉(zhuǎn)、異常處理、線程恢復(fù)等基礎(chǔ)功能都要考程序計(jì)數(shù)器。(記住程序當(dāng)前走到的位置,下次還回來(lái))。線程私有。
2. Java虛擬機(jī)棧(線程私有)
和方法相關(guān)聯(lián),每個(gè)方法在執(zhí)行的同時(shí)都會(huì)創(chuàng)建一個(gè)棧幀用于存儲(chǔ)局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口等信息。每一個(gè)方法從調(diào)用直至執(zhí)行完成的過(guò)程,就對(duì)應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中入棧到出棧的過(guò)程
線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的深度,將拋出StackOverflowError異常(常見(jiàn)的遞歸層數(shù)過(guò)多導(dǎo)致”爆棧“)
3. 本地方法棧(線程私有)
類似于Java虛擬機(jī)棧。區(qū)別在于:
虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java方法本地方法棧則為虛擬機(jī)使用到的Native方法服務(wù)
Java開(kāi)頭通過(guò)Java Native Interface來(lái)調(diào)用本地方法(一般用C語(yǔ)言編寫)
4. Java堆(線程共享)
Java虛擬機(jī)所管理的內(nèi)存中最大的一塊new出來(lái)的對(duì)象就存在于堆上垃圾收集器管理的主要區(qū)域
5. 方法區(qū)(線程共享)
存儲(chǔ)已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量
6. 運(yùn)行時(shí)常量池
方法區(qū)的一部分用于存放編譯期生成的各種字面量和符號(hào)引用
2. 對(duì)象是如何創(chuàng)建的?
Object obj=new Object(): 分析這行代碼的執(zhí)行過(guò)程
使用了new關(guān)鍵字,檢查這個(gè)指令的參數(shù)是否能在常量池中定位到一個(gè)類的符號(hào)引用,并且檢查這個(gè)符號(hào)引用代表的類是否已被加載、解析和初始化過(guò)。沒(méi)有的話先加載類類加載檢查通過(guò)后,虛擬機(jī)將為新生對(duì)象分配內(nèi)存內(nèi)存分配完成后,虛擬機(jī)需要將分配到的內(nèi)存空間都初始化為零值虛擬機(jī)要對(duì)對(duì)象進(jìn)行必要的設(shè)置,例如將對(duì)象的哈希碼、元數(shù)據(jù)、GC分代年齡、是否使用偏向鎖等數(shù)據(jù)存放在對(duì)象頭中執(zhí)行init方法,把對(duì)象按照程序員的意愿進(jìn)行初始化(給成員變量賦的值)
3. 對(duì)象的內(nèi)存布局


4. 對(duì)象的訪問(wèn)定位
1. 句柄訪問(wèn)
Java堆中將會(huì)劃分出一塊內(nèi)存來(lái)作為句柄池,reference中存儲(chǔ)的就是對(duì)象的句柄地址,而句柄中包含了對(duì)象實(shí)例數(shù)據(jù)與類型數(shù)據(jù)各自的具體地址信息

2. 直接指針訪問(wèn)
Java堆對(duì)象的布局中就必須考慮如何放置訪問(wèn)類型數(shù)據(jù)的相關(guān)信息,而reference中存儲(chǔ)的直接就是對(duì)象地址

二者比較:
使用句柄來(lái)訪問(wèn)的最大好處就是reference中存儲(chǔ)的是穩(wěn)定的句柄地址,即使對(duì)象被移動(dòng)(GC過(guò)程),只需要改變句柄中的示例指針,無(wú)需變動(dòng)refrence直接指針訪問(wèn)方式的最大好處就是速度更快, refrence直接指向?qū)嵗龜?shù)據(jù),減少了一次指針訪問(wèn)
HotSpot虛擬機(jī)使用直接指針?lè)绞竭M(jìn)行對(duì)象訪問(wèn)的
5. OutOfMemoryError異常代碼演示
1. Java堆溢出
package jvm;
import java.util.ArrayList;
import java.util.List;
public class OutOfMemoryErrorDemo {
static class MyObject{
}
public static void main(String[] args) {
List<MyObject> list=new ArrayList<>();
int i=0;
while(true)
{
System.out.println(i++);
list.add(new MyObject());
}
}
}


限制Java堆的大小為20MB,不可擴(kuò)展(將堆的最小值-Xms參數(shù)與最大值-Xmx參數(shù)設(shè)置為一樣即可避免堆自動(dòng)擴(kuò)展),通過(guò)參數(shù)-XX:+HeapDumpOnOutOfMemoryError可以讓虛擬機(jī)在出現(xiàn)內(nèi)存溢出異常時(shí)Dump出當(dāng)前的內(nèi)存堆轉(zhuǎn)儲(chǔ)快照以便事后進(jìn)行分析
2. 虛擬機(jī)棧溢出
如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的最大深度,將拋出StackOverflowError異常
package jvm;
import java.util.ArrayList;
import java.util.List;
public class OutOfMemoryErrorDemo {
static int i=0;
public static void main(String[] args) {
f();
}
public static void f() {
System.out.println(i++);
f();
}
}


相同的Xss(線程的堆棧大小)下,如果棧中的本地?cái)?shù)據(jù)較多,那么相應(yīng)的可以遞歸的次數(shù)就越少
還有1種棧溢出會(huì)報(bào)OutOfMemoryError異常,如果虛擬機(jī)在擴(kuò)展棧時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存空間,則拋出OutOfMemoryError異常,比如將上面的遞歸改成多線程版就會(huì)出現(xiàn)這種問(wèn)題
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
利用MyBatis-Plus靈活處理JSON字段的技巧與最佳實(shí)踐
這篇文章主要給大家介紹了關(guān)于利用MyBatis-Plus靈活處理JSON字段的技巧與最佳實(shí)踐,Mybatis-Plus可以很方便地處理JSON字段,在實(shí)體類中可以使用@JSONField注解來(lái)標(biāo)記JSON字段,需要的朋友可以參考下2024-07-07
idea打開(kāi)項(xiàng)目后無(wú)法顯示目錄結(jié)構(gòu),只能顯示.iml文件問(wèn)題
這篇文章主要介紹了idea打開(kāi)項(xiàng)目后無(wú)法顯示目錄結(jié)構(gòu),只能顯示.iml文件問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
Springboot內(nèi)置的工具類之CollectionUtils示例講解
這篇文章主要介紹了Springboot內(nèi)置的工具類之CollectionUtils,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12
Java8新特性之泛型的目標(biāo)類型推斷_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
泛型是Java SE 1.5的新特性,泛型的本質(zhì)是參數(shù)化類型,也就是說(shuō)所操作的數(shù)據(jù)類型被指定為一個(gè)參數(shù)。下面通過(guò)本文給分享Java8新特性之泛型的目標(biāo)類型推斷,感興趣的朋友參考下吧2017-06-06
spring cloud中微服務(wù)之間的調(diào)用以及eureka的自我保護(hù)機(jī)制詳解
這篇文章主要介紹了spring cloud中微服務(wù)之間的調(diào)用以及eureka的自我保護(hù)機(jī)制詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
SpringBoot注解@ConditionalOnClass底層源碼實(shí)現(xiàn)
這篇文章主要為大家介紹了SpringBoot注解@ConditionalOnClass底層源碼實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
IntelliJ IDEA導(dǎo)入Gradle項(xiàng)目的方法
這篇文章主要介紹了IntelliJ IDEA導(dǎo)入Gradle項(xiàng)目的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
SpringBoot集成elasticsearch使用圖文詳解
Spring Boot集成Elasticsearch其實(shí)非常簡(jiǎn)單,這篇文章主要給大家介紹了關(guān)于SpringBoot集成elasticsearch使用的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04

