JVM
Java 程式碼在運作時, 會透過 compiler 將程式碼編譯為 *.class
的檔案, 而這個檔案會透過 Java Virtual Machine (JVM) 將其轉為 byte code, 讓作業系統執行運作, 而在 JVM 裏面, 會把 java 的資料類型分為 primitive 與 reference, 這樣設計是考量 JVM 在運行之前希望由 compiler 先將所有資料進行檢查.
Primitive type
primitive 類型支持如, byte
(8bits), short
(16bits), int
(32bits), long
(64bits), char(16bits).
Reference type
而 reference 類型有, class
, array
, interface
, 他們的默認值為 null
.
JVM Stack
JVM STACK 會隨著 JVM 的 THREAD 建立而跟著建立, THREAD 是執行緒, 最少會有一個 Main 的主要執行序. 每個 THREAD 則會依據程式的運行深度, 而使用 STACK 空間, STACK 空間是私有的, 不能與其他 THREAD 共用. STACK 裏面用來存放的每個操作叫做 FRAMES, 在 IntelliJ debug 模式中可觀察到.
在 THREADS 籤頁中除了看到 main 的主執行緒外, 還有 7 個 GC Slave (記憶體回收) 的執行緒在運行, 跟一堆 JVM 的其他 THREADS.
在 FRAMES 階段, 切換到 MAIN THREAD, 可以看到下面灰階的部分有 Lambda 跟 Jupiter 套件的運作紀錄.
STACK 在資料結構的定義是一種後進先出的資料結構(LIFO), 這是一個很方便用於資料反轉 (Reverse) 的資料結構. 所以當程式拋出 Exceptions 可以透過 e.printStackTrace()
來取得當前 THREAD 使用 STACK 所有過程.
try {
// do something
} catch (Exception e) {
// 輸出 exception 所記錄的 stack trace
e.printStackTrace();
}
STACK 的大小
STACK 可以想像成, 當前的 THREAD 要走多深. 在文件所定義的 JVM 規範中, 允許 STACK 動態的增加擴充, 但也允許讓開發者去設定 JVM 的 STACK 大小, 可以使用 java -Xss1M
這樣的設定去啟動 JVM, 宣告 STACK 大小為 1Mb 空間.
STACK 的空間估計, 通常取決於要跑幾個 THREADs, 而這又與 CPUs 的計算能力有關.
# run myApp jar with 1Mb mem.
java -Xss:1M myApp
當 STACK 超過 THREAD 的最大深度時, 會拋出
StackOverflowError
, 比如說在無限遞迴的情境.當 JVM 要擴增 STACK 空間時, 但沒有足夠的記憶體可以拿來擴展 STACK 與 THREAD 時, 會拋出
OutOfMemoryError
.
JVM Heap
JVM Heap 是在 JVM 啟動時建立的, 但是屬於 Threads 共用的, 主要用來存放 class, array 類型, 由 GC 機制做回收, HEAP 跟 STACK 一樣, 也是可以由開發者去定義大小. 為了有最佳的效能, 官方頁面設定是說建議 Xms
與 Xmx
可設定相同的大小, 若沒有特別指定的話, 預設會使用系統的 25% 實體記憶體做設定, 另外 server mode 與 client mode 也會有所差異.
Java Visualizer
若想要在 Local 觀察 STACK 與 HEAP 的運作的話, 在 InteiilJ 的環境下可以安裝 java-visualizer, 透過 debug 的 step over 就能確實觀察到 STACK 與 HEAP 的運作.
Reference
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5.2
https://alvinalexander.com/scala/fp-book/recursion-jvm-stacks-stack-frames
https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html#wp1024112
https://fa20.datastructur.es/materials/guides/plugin.html#java-visualizer