OutOfMemoryError內(nèi)存不足和StackOverflowError堆棧溢出示例詳解
OutOfMemoryError(內(nèi)存不足)
如果虛擬機的棧內(nèi)存允許動態(tài)擴展,當(dāng)擴展棧容量無法申請到足夠的內(nèi)存時,將拋出
OutOfMemoryError異常。
StackOverflowError(堆棧溢出)
如果線程請求的棧深度大于虛擬機所允許的最大深度,將拋出StackOverflowError異常。
測試一:單線程中通過兩個方法不斷相互調(diào)用
單線程中,通過兩個方法不斷的相互調(diào)用,棧的深度到達了虛擬機的最大深度。
結(jié)果:拋出StackOverflowError異常,
public class JVMStackOverflow { static void dfs(){ a(); } private static void a() { dfs(); } public static void main(String[] args) throws Throwable { dfs(); } }
測試二:使用單線程,定義了大量的本地變量
使用單線程,定義了大量的本地變量,增大此方法幀中本地變量表的長度。
結(jié)果:拋出StackOverflowError異常,異常出現(xiàn)時輸出的堆棧深度相應(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; } } }
可見無論是由于棧幀太大還是虛擬機棧容量太小,當(dāng)新的棧幀內(nèi)存無法分配的時候,HotSpot虛擬機拋出的都是StackOverflowError異常??墒侨绻谠试S動態(tài)擴展棧容量大小的虛擬機上,相同代碼則會導(dǎo)致不一樣的情況。譬如遠古時代的Classic虛擬機,這款虛擬機可以支持動態(tài)擴展棧內(nèi)存的容量,它運行方法二就會產(chǎn)生OutOfMemoryError異常。
測試三:什么情況下可以產(chǎn)生OutOfMemoryError異常呢?
通過不斷建立線程的方式,在HotSpot上也是可以產(chǎn)生內(nèi)存溢出異常的。但是這樣產(chǎn)生的內(nèi)存溢出異常和??臻g是否足夠并不存在任何直接的關(guān)系,主要取決于操作系統(tǒng)本身的內(nèi)存使用狀態(tài)。甚至可以說,在這種情況下,給每個線程的棧分配的內(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堆棧溢出示例詳解的詳細內(nèi)容,更多關(guān)于OutOfMemoryError StackOverflowError的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java基礎(chǔ)教程之對象的方法與數(shù)據(jù)成員
這篇文章主要介紹了Java基礎(chǔ)教程之對象的方法與數(shù)據(jù)成員,本文講解對象的方法與數(shù)據(jù)成員相關(guān)知識,因為java是面向?qū)ο笳Z言,本文的知識都是經(jīng)常要用到的,需要的朋友可以參考下2014-08-08@RequestBody注解Ajax post json List集合數(shù)據(jù)請求400/41
這篇文章主要介紹了@RequestBody注解Ajax post json List集合數(shù)據(jù)請求400/415的處理方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10Java?synchronized關(guān)鍵字性能考量及優(yōu)化探索
這篇文章主要為大家介紹了Java?synchronized關(guān)鍵字性能考量及優(yōu)化探索示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12java根據(jù)擴展名獲取系統(tǒng)圖標和文件圖標示例
這篇文章主要介紹了java根據(jù)擴展名獲取系統(tǒng)圖標和文件圖標示例,需要的朋友可以參考下2014-03-03SpringBoot在自定義類中調(diào)用service層mapper層方式
這篇文章主要介紹了SpringBoot在自定義類中調(diào)用service層mapper層方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-03-03