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 程式所需的兩個記憶體空間開始本文。在後面的部分中,我們討論了與堆和棧記憶體相關的錯誤。

更新於:2023-07-21

218 次檢視

啟動您的 職業生涯

透過完成課程獲得認證

開始
廣告