Java 中的堆和棧記憶體錯誤
在 Java 中,執行程式的每個介面、類、物件、變數和方法都儲存在計算機記憶體的不同區域。堆是記憶體區域的一部分,其中變數、方法和類的值在執行時儲存。它的分配是動態發生的,並且可以根據應用程式的需求增長或縮小。另一方面,引用變數、方法和類的名稱儲存在棧記憶體區域。但是,如果由於某種原因其分配沒有得到正確處理,則可能導致記憶體錯誤,我們將在本文中討論這些錯誤。
與棧相關的錯誤
每當一個程序啟動時,它都會自動定義一個固定的棧大小。在每次方法呼叫期間,會在呼叫棧上建立一個呼叫幀,並且會一直持續到方法呼叫結束。當計算機記憶體的棧空間中沒有剩餘空間用於新的棧幀時,我們就會遇到**StackOverflowError**。
示例 1
以下示例說明了 StackOverflowError
import java.lang.StackOverflowError; public class Overflw { public static void methodA(int n1) { n1++; methodB(n1); } public static void methodB(int n1) { n1++; methodA(n1); } public static void main(String []args) { int n1 = 0; methodA(n1); } }
輸出
Exception in thread "main" java.lang.StackOverflowError at Overflw.methodB(Overflw.java:10) at Overflw.methodA(Overflw.java:6) at Overflw.methodB(Overflw.java:10) at Overflw.methodA(Overflw.java:6) at Overflw.methodB(Overflw.java:10) at Overflw.methodA(Overflw.java:6) at Overflw.methodB(Overflw.java:10)
如您所見,示例 1 程式碼的輸出是 StackOverflowError。在這裡,我們建立了兩個名為“methodA”和“methodB”的引數化使用者定義方法。在主方法中,我們宣告並初始化了一個整數變數“n1”為 0,並呼叫了“methodA”以及引數“n1”。現在,“methodA”呼叫了“methodB”並傳遞了“n1”的增量值。同樣,“methodB”呼叫了“methodA”,並且此過程重複多次。因此,在某些時候,為該程式建立的棧大小耗盡,從而導致以下錯誤。
我們可以採取以下措施來處理 StackOverflowError
為重複自身的方法提供適當的終止條件
減少區域性變數或陣列的大小也可能有所幫助。
重構程式碼以避免無限方法呼叫。
示例 2
現在,藉助此示例,我們將嘗試找到在先前示例中發生的 StackOverflowError 的解決方案。
public class Overflw { public static void methodA(int n1) { n1++; methodB(n1); } public static void methodB(int n1) { n1++; int n2 = 5; int mult = n1 * n2; System.out.println("Value of n1 and n2 multiplication is: " + mult); } public static void main(String []args) { int n1 = 0; methodA(n1); } }
輸出
Value of n1 and n2 multiplication is: 10
在示例 1 中,程式碼的問題是第 6 行和第 10 行沒有終止。但在上面的示例中,我們提供了一個終止程式並列印“mult”中儲存值的語句。
與堆相關的錯誤
JVM 的兩個屬性“-Xmx”和“-Xms”決定了堆的大小。此大小會影響值的儲存。當 JVM 由於堆記憶體部分空間不足而無法分配值時,我們就會遇到**OutOfMemoryError**。
示例 1
以下示例說明了 OutOfMemoryError。
public class MemoryErr { public static void main(String[] args) { String stAray[] = new String[100 * 100 * 100000]; } }
輸出
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at MemoryErr.main(MemoryErr.java:3)
在上面的程式碼中,我們分配了一個大於堆大小的空間,因此我們得到了 OutOfMemoryError
我們可以採取以下措施來處理 OutOfMemoryError。
我們可以使用 -Xmx 和 -Xms JVM 選項增加堆的大小
使用適合應用程式行為的垃圾收集器也可能有所幫助。
示例 2
以下示例說明了如何使用 try 和 catch 塊處理 OutOfMemoryError。
public class MemoryErr { public static void main(String[] args) { try { String stAray[] = new String[100 * 100 * 100000]; } catch(OutOfMemoryError exp) { System.out.println("Application reached Max size of Heap"); } } }
輸出
Application reached Max size of Heap
結論
我們從解釋每個 Java 程式所需的兩個記憶體空間開始本文。在後面的部分中,我們討論了與堆和棧記憶體相關的錯誤。