JVM stack and heap

更新於 發佈於 閱讀時間約 4 分鐘

Java Visualizer

使用 intelliJ IDE 開發工具的話, 建議可以安裝 java-visualizer 來觀察。
首先關注 a, b 這 2 個變數, 於 call stack 區塊的顯示, 變數 a 是 primitive type 可以直接存放於 stack 空間, 原本以為 b 會有 Objects 紀錄, 原因是 Integer 在編譯為 byte code 時會變成 byteshort 存入 stack, 真是太神奇了 Jack。
可以參照 StackOverflow 解釋, 但我沒有深究
而變數 list 則是明顯的產生一個 Reference 參照到 Objects 裡面的 ArrayList 物件。

JVM 什麼時候使用 stack 什麼時候使用 heap ?

我個人覺得比較好理解的方式是, 從 StackOverflowErrorOutOfMemoryError 這兩個錯誤去認識 StackHeap
StackOverflowError 觸發的條件在於產生大量的 stack memory 直到超過 JVM 設定的 stack 大小。簡單測試如下:
public static void main(String[] args) {
recursive(1);
}
// 這裡是一個無限遞迴, 每次遞迴都會使用一塊 stack 空間
private static void recursive(int i) {
System.out.println("print: " + i);
recursive(++i);
}
依據 Oracle 的文件描述, stack 可以是固定大小或是動態擴展的, 可以使用 java -Xss1M 這樣的設定去啟動 JVM, 宣告 stack 大小為 1Mb 空間。
This specification permits Java Virtual Machine stacks either to be of a fixed size or to dynamically expand and contract as required by the computation.
-Xss 的設定會依據 JVM 的環境, 或是 OS 的環境而有所差異, 這是 Oracle 提供的簡略參考對照表
https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html#wp1024112
OutOfMemoryError 的觸發條件, 源自於超過 Heap 使用上限, 搭配 -Xmx1M 很容易就達到。
public static void main(String[] args) {
  // 由於限制了 1Mb 的 Heap 使用量, 所以根本無法產生大空間的 intArray
Integer[] intArray = new Integer[Integer.MAX_VALUE];
System.out.println(intArray);
}

總結

Stack 的空間用於 primitive type 或是用於指向 object reference, 依據官方文件描述, 每個 threads 都會有自己的 stack; 而 Heap 空間用於 Objects 實際上使用的空間。
若採用多執行緒的設計, Heap 空間就需要特別留意 OOM 問題, 特別是在 Microservice 的環境下, Replica 的設定沒有估計, 很容易就不小心吃掉大量記憶體, 導致同一個 Node 底下的服務因為記憶體不夠而不停重啟。
// JVM 使用的記憶體最大值
N-threads * Xms size = JVM Heap Size
avatar-img
0會員
2內容數
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
你可能也想看
Google News 追蹤
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
本章節的目的是介紹Java中的套件使用,包括如何引用第三方套件和自定義模組,如何創建和使用自定義套件,以及介紹一些常見的Java標準庫套件。這些內容將幫助讀者更好地理解和使用Java的套件系統。
Thumbnail
本章節的目的是介紹Java中的運算符,包括算數運算符、比較運算符、賦值運算符、位元運算符以及運算符的優先等級。通過本章節,讀者可以了解到如何在Java中進行基本的數學運算、比較兩個值的大小、將值賦給變數、進行位元運算,以及在複雜表達式中如何正確地理解運算符的優先等級。
Thumbnail
此章節旨在介紹Java程式語言中的各種資料型別,包括基本型別、引用型別、集合型別、陣列型別、字典型別等。它還講解了如何在Java中進行型別轉換和自定義型別,並提供了相關的程式碼示例。
Thumbnail
此章節旨在介紹Java的基本語法、註解和變數的使用。透過學習,讀者將了解Java程式的基本結構、程式進入點的定義、如何撰寫單行和多行註解,以及如何宣告和初始化變數。
Thumbnail
這篇文章的目的是對Java程式設計語言進行介紹,包括它的特性、應用範疇、主要使用者,以及相關的學習資源和常見的庫與框架。此外,它也提供了一些學習Java的渠道,以及與Java相關的其他知識。
Thumbnail
Lazy evaluation 的效益必須是在 pipe 的組合上有最佳化過的,若組合的不好反而更糟糕,且在 I/O 上幫助似乎也不大。parallel stream 要能發揮效果必須看資料的來源類型,不過要注意的是 parallel stream 也會使記憶體的使用量增加,使用上也要小心。
Thumbnail
老實說,看到 Java Sream API 讓我感到相當親切,這應該跟我研究所多年的研究題目是 visual dataflow language 有關,Java Stream API 把迴圈給內化了,每個 operation 的重點是要做什麼,大大提高了程式的抽象化程度和可讀性。
前言: 雖然前面有些定義還沒有完整的解釋,但還是後面再說吧, 誰想一直看理論啊(摔本子)
※ 認識變數: 變數(variable)是在程式裡面把東西存起來的概念。 基於不讓電腦每次都需要重新運算,把需要花時間運算的東西先存起來,之後再直接拿出來使用,所以我們需要變數。 變數儲存的位置在電腦裡的記憶體。變數就像是一個箱子,記憶體就像是一個倉庫。箱子的名稱就是變數名稱,箱子的內容物就是
Thumbnail
JS 資料型別分為兩大類,原始型別 (Primitive values) 和物件型別 (Objects)。
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
本章節的目的是介紹Java中的套件使用,包括如何引用第三方套件和自定義模組,如何創建和使用自定義套件,以及介紹一些常見的Java標準庫套件。這些內容將幫助讀者更好地理解和使用Java的套件系統。
Thumbnail
本章節的目的是介紹Java中的運算符,包括算數運算符、比較運算符、賦值運算符、位元運算符以及運算符的優先等級。通過本章節,讀者可以了解到如何在Java中進行基本的數學運算、比較兩個值的大小、將值賦給變數、進行位元運算,以及在複雜表達式中如何正確地理解運算符的優先等級。
Thumbnail
此章節旨在介紹Java程式語言中的各種資料型別,包括基本型別、引用型別、集合型別、陣列型別、字典型別等。它還講解了如何在Java中進行型別轉換和自定義型別,並提供了相關的程式碼示例。
Thumbnail
此章節旨在介紹Java的基本語法、註解和變數的使用。透過學習,讀者將了解Java程式的基本結構、程式進入點的定義、如何撰寫單行和多行註解,以及如何宣告和初始化變數。
Thumbnail
這篇文章的目的是對Java程式設計語言進行介紹,包括它的特性、應用範疇、主要使用者,以及相關的學習資源和常見的庫與框架。此外,它也提供了一些學習Java的渠道,以及與Java相關的其他知識。
Thumbnail
Lazy evaluation 的效益必須是在 pipe 的組合上有最佳化過的,若組合的不好反而更糟糕,且在 I/O 上幫助似乎也不大。parallel stream 要能發揮效果必須看資料的來源類型,不過要注意的是 parallel stream 也會使記憶體的使用量增加,使用上也要小心。
Thumbnail
老實說,看到 Java Sream API 讓我感到相當親切,這應該跟我研究所多年的研究題目是 visual dataflow language 有關,Java Stream API 把迴圈給內化了,每個 operation 的重點是要做什麼,大大提高了程式的抽象化程度和可讀性。
前言: 雖然前面有些定義還沒有完整的解釋,但還是後面再說吧, 誰想一直看理論啊(摔本子)
※ 認識變數: 變數(variable)是在程式裡面把東西存起來的概念。 基於不讓電腦每次都需要重新運算,把需要花時間運算的東西先存起來,之後再直接拿出來使用,所以我們需要變數。 變數儲存的位置在電腦裡的記憶體。變數就像是一個箱子,記憶體就像是一個倉庫。箱子的名稱就是變數名稱,箱子的內容物就是
Thumbnail
JS 資料型別分為兩大類,原始型別 (Primitive values) 和物件型別 (Objects)。