Java棧溢位|記憶體洩漏|記憶體溢位

救苦救难韩天尊發表於2024-08-13

Java虛擬機器棧是執行緒私有的,它的生命週期和執行緒同步

一個執行緒每執行到一個方法,JVM就會建立一個棧幀(用於儲存基本資料型別、物件指標和返回值等),並將棧幀壓入棧中。

程式碼示例:

public class Example {
    public static void main(String[] args) {
        Example example = new Example();
        example.m1();
    }

    public void m1() {
        int x = 0;
        m2();
    }
    public void m2() {
        Apple y = new Apple();
        m3();
    }
    public void m3() {
        float z = 1.0f;
    }
}

執行流程:

Java棧溢位|記憶體洩漏|記憶體溢位
  • 首先,程式啟動,main() 方法入棧。
  • 然後,m1() 方法入棧,宣告 int 型別變數 x = 0。注意,無論是 x 還是 0 都儲存在棧幀中。
  • 接著,m2() 方法入棧,建立了一個 Apple 物件,並被賦給變數 y。請注意,實際的 Apple 物件是在 Java 堆記憶體中建立的,而不是執行緒棧中,只有 Apple 物件的引用以及變數 y 被包含在棧幀裡。
  • 最後,m3() 方法入棧,宣告 float 型別變數 z = 1.0f。同理,z 和 1.0f 都被儲存在棧幀裡。

當方法執行完成後,所有的執行緒棧幀將按照後進先出的順序逐一出棧,直至棧空為止

img

Java執行緒棧預設大小是由作業系統決定的,一般為1MB或2MB。如果需要調整執行緒棧的大小,可以使用-Xss引數來設定。在實際開發中,預設的執行緒棧大小通常已經足夠滿足需求,只有在遇到執行緒棧溢位錯誤時才需要考慮調整大小。

一旦遞迴過深,執行緒棧的容量增長超過了允許的棧容量,就會丟擲StackOverflowError(棧溢位) 錯誤。

那麼什麼是記憶體洩漏和記憶體溢位呢?

  • 記憶體溢位(out of memory):指程式在申請記憶體時,沒有足夠的記憶體空間供其使用。
  • 記憶體洩露(memory leak):指程式在申請記憶體後,無法釋放已申請的記憶體空間,進而導致記憶體逐漸被佔光。
  • memory leak 最終會導致 out of memory。

記憶體溢位異常丟擲的原因(包括但不限於):

  • 如果新執行緒在申請棧時失敗了,就會丟擲 OutOfMemoryError(記憶體溢位) 錯誤。
  • 或者當JVM不能分配給物件的建立空間,也會丟擲 OutOfMemoryError 錯誤。

小結:

  • StackOverflowError:遞迴過深,遞迴沒有出口。
  • MemoryLeak:申請記憶體後,無法釋放已申請的記憶體空間。
  • OutOfMemoryError:JVM空間溢位,建立物件速度高於GC回收速度。

相關文章