OutOfMemoryError內(nèi)存不足和StackOverflowError堆棧溢出示例詳解
OutOfMemoryError(內(nèi)存不足)
如果虛擬機(jī)的棧內(nèi)存允許動(dòng)態(tài)擴(kuò)展,當(dāng)擴(kuò)展棧容量無(wú)法申請(qǐng)到足夠的內(nèi)存時(shí),將拋出
OutOfMemoryError異常。
StackOverflowError(堆棧溢出)
如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的最大深度,將拋出StackOverflowError異常。
測(cè)試一:?jiǎn)尉€程中通過(guò)兩個(gè)方法不斷相互調(diào)用
單線程中,通過(guò)兩個(gè)方法不斷的相互調(diào)用,棧的深度到達(dá)了虛擬機(jī)的最大深度。
結(jié)果:拋出StackOverflowError異常,
public class JVMStackOverflow {
static void dfs(){
a();
}
private static void a() {
dfs();
}
public static void main(String[] args) throws Throwable {
dfs();
}
}
測(cè)試二:使用單線程,定義了大量的本地變量
使用單線程,定義了大量的本地變量,增大此方法幀中本地變量表的長(zhǎng)度。
結(jié)果:拋出StackOverflowError異常,異常出現(xiàn)時(shí)輸出的堆棧深度相應(yīng)縮小。
public class JavaVMStackSOF {
private static int stackLength = 0;
public static void test() {
long unused1, unused2, unused3, unused4, unused5,
unused6, unused7, unused8, unused9, unused10,
unused11, unused12, unused13, unused14, unused15,
unused16, unused17, unused18, unused19, unused20,
unused21, unused22, unused23, unused24, unused25,
unused26, unused27, unused28, unused29, unused30,
unused31, unused32, unused33, unused34, unused35,
unused36, unused37, unused38, unused39, unused40,
unused41, unused42, unused43, unused44, unused45,
unused46, unused47, unused48, unused49, unused50,
unused51, unused52, unused53, unused54, unused55,
unused56, unused57, unused58, unused59, unused60,
unused61, unused62, unused63, unused64, unused65,
unused66, unused67, unused68, unused69, unused70,
unused71, unused72, unused73, unused74, unused75,
unused76, unused77, unused78, unused79, unused80,
unused81, unused82, unused83, unused84, unused85,
unused86, unused87, unused88, unused89, unused90,
unused91, unused92, unused93, unused94, unused95,
unused96, unused97, unused98, unused99, unused100;
stackLength ++;
test();
unused1 = unused2 = unused3 = unused4 = unused5 =
unused6 = unused7 = unused8 = unused9 = unused10 =
unused11 = unused12 = unused13 = unused14 = unused15 =
unused16 = unused17 = unused18 = unused19 = unused20 =
unused21 = unused22 = unused23 = unused24 = unused25 =
unused26 = unused27 = unused28 = unused29 = unused30 =
unused31 = unused32 = unused33 = unused34 = unused35 =
unused36 = unused37 = unused38 = unused39 = unused40 =
unused41 = unused42 = unused43 = unused44 = unused45 =
unused46 = unused47 = unused48 = unused49 = unused50 =
unused51 = unused52 = unused53 = unused54 = unused55 =
unused56 = unused57 = unused58 = unused59 = unused60 =
unused61 = unused62 = unused63 = unused64 = unused65 =
unused66 = unused67 = unused68 = unused69 = unused70 =
unused71 = unused72 = unused73 = unused74 = unused75 =
unused76 = unused77 = unused78 = unused79 = unused80 =
unused81 = unused82 = unused83 = unused84 = unused85 =
unused86 = unused87 = unused88 = unused89 = unused90 =
unused91 = unused92 = unused93 = unused94 = unused95 =
unused96 = unused97 = unused98 = unused99 = unused100 = 0;
}
public static void main(String[] args) {
try {
test();
}catch (Error e){
System.out.println("stack length:" + stackLength);
throw e;
}
}
}
可見(jiàn)無(wú)論是由于棧幀太大還是虛擬機(jī)棧容量太小,當(dāng)新的棧幀內(nèi)存無(wú)法分配的時(shí)候,HotSpot虛擬機(jī)拋出的都是StackOverflowError異常??墒侨绻谠试S動(dòng)態(tài)擴(kuò)展棧容量大小的虛擬機(jī)上,相同代碼則會(huì)導(dǎo)致不一樣的情況。譬如遠(yuǎn)古時(shí)代的Classic虛擬機(jī),這款虛擬機(jī)可以支持動(dòng)態(tài)擴(kuò)展棧內(nèi)存的容量,它運(yùn)行方法二就會(huì)產(chǎn)生OutOfMemoryError異常。
測(cè)試三:什么情況下可以產(chǎn)生OutOfMemoryError異常呢?
通過(guò)不斷建立線程的方式,在HotSpot上也是可以產(chǎn)生內(nèi)存溢出異常的。但是這樣產(chǎn)生的內(nèi)存溢出異常和??臻g是否足夠并不存在任何直接的關(guān)系,主要取決于操作系統(tǒng)本身的內(nèi)存使用狀態(tài)。甚至可以說(shuō),在這種情況下,給每個(gè)線程的棧分配的內(nèi)存越大,反而越容易產(chǎn)生內(nèi)存溢出異常。
public class JVMStackOOM {
private void dontStop() {
while (true) {
}
}
public void stackLeakByThread() {
while (true) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
dontStop();
}
});
thread.start();
}
}
public static void main(String[] args) throws Throwable {
JVMStackOOM oom = new JVMStackOOM();
oom.stackLeakByThread();
}
}以上就是OutOfMemoryError內(nèi)存不足和StackOverflowError堆棧溢出示例詳解的詳細(xì)內(nèi)容,更多關(guān)于OutOfMemoryError StackOverflowError的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
IntelliJ IDEA查看項(xiàng)目git路徑的三種方式
這篇文章主要介紹了IntelliJ IDEA查看項(xiàng)目git路徑的三種方式,文中通過(guò)圖文結(jié)合的方式講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-12-12
教你用Java Swing實(shí)現(xiàn)自助取款機(jī)系統(tǒng)
詳解SpringSecurity如何實(shí)現(xiàn)前后端分離
詳解springboot中各個(gè)版本的redis配置問(wèn)題

