Java 虛擬機棧詳解分析
Java虛擬機棧
1. 定義
- 棧:線程運行時需要的內(nèi)存空間,一個棧存在多個棧幀。棧具有先入后出,后入先出的特點。
- 棧幀:每個方法運行時需要的內(nèi)存(局部變量表、操作數(shù)棧、動態(tài)鏈接和方法返回值等信息。),每次調(diào)用一個方法,便會將棧幀壓入棧中,方法執(zhí)行完畢將棧幀從棧頂壓出
- 活動棧幀:指在棧頂?shù)臈?,既正在調(diào)用的方法,每個線程只能有一個活動棧幀,對應(yīng)著該線程正在調(diào)用的那個方法
現(xiàn)在我們用代碼來演示一下Java虛擬機如何將棧幀壓入及壓出棧中
public class Main {
public static void main(String[] args) {
method1();
}
private static void method1() {
method2(1, 2);
}
private static int method2(int a, int b) {
int c = a + b;
return c;
}
}
當我們運行Main函數(shù)時,jvm首先將棧幀Main壓入棧中,此視棧結(jié)構(gòu)如圖所示

Main函數(shù)體中調(diào)用了method1方法,此時便會將棧幀1壓入棧中

method1方法體中調(diào)用了method2方法,這時jvm會將棧幀2壓入棧結(jié)構(gòu)中,需要注意的是,前面我們提到了棧幀由 “局部變量表、操作數(shù)棧、動態(tài)鏈接和方法返回值”等信息組成,method2方法中擁有a,b兩個參數(shù)以及局部變量c和方法返回值

當method2方法執(zhí)行完后,會將棧幀2從棧頂彈出

method1方法執(zhí)行完畢后,將棧幀1彈出

依次順序直至線程被銷毀。
注意點
- 由于每個棧幀都會在方法調(diào)用完畢后被彈出,因此棧內(nèi)存不需要進行垃圾回收
- 每個棧都是線程私有的,每個線程在創(chuàng)建的時候都會創(chuàng)建一個虛擬機棧,而由于物理內(nèi)存是固定的,棧內(nèi)存劃分得越大,可分配的線程數(shù)就越少
2. 棧的線程安全問題
局部變量是線程安全的
現(xiàn)在我們定義如下方法:
public static void method() {
int a = 0;
a++;
}
我們在方法method中定義了一個局部變量a,并對其執(zhí)行a++操作,現(xiàn)在假設(shè)我們有兩個線程同時調(diào)用了這個方法(棧幀),Java虛擬機會將該棧幀壓入各自線程的棧內(nèi)存中,但由于局部變量表是線程私有的,所以兩個線程在同時調(diào)用這個棧幀后,a的值仍然都為1,故局部變量是線程安全的

方法參數(shù)和方法返回值不是線程安全
由于方法的參數(shù)和返回值均可被外部方法所引用,故在某個線程下某個方法可以更改另外一個方法的參數(shù)和返回值,故方法參數(shù)和方法返回值不是線程安全的
3. 棧內(nèi)存溢出
由于程序執(zhí)行時,虛擬機給每個棧分配的棧內(nèi)存空間是固定的,所以在一些情況下有可能出現(xiàn)棧內(nèi)存空間不足,導(dǎo)致溢出的情況,一般有兩種情況可能導(dǎo)致棧內(nèi)存溢出
- 棧幀過大(較少出現(xiàn))
- 棧幀過多(一般出現(xiàn)在遞歸時。沒有正確設(shè)置遞歸出口)
現(xiàn)在我們來解釋一下什么時候會出現(xiàn)棧幀過多導(dǎo)致棧內(nèi)存溢出,我們來假設(shè)某一個棧的內(nèi)存空間大小是1024kb,現(xiàn)在有四個棧幀,每個棧幀的大小均為300kb,而 300 * 4 = 1200kb, 而 1200 > 1024 ,很顯然,現(xiàn)在這四個棧幀合起來的大小已經(jīng)超過了這個棧的內(nèi)存空間大小,這個時候就會出現(xiàn)棧內(nèi)存溢出,也就是會報java.lang.StackOverflowError這個錯誤。

到此這篇關(guān)于Java 虛擬機棧詳解分析的文章就介紹到這了,更多相關(guān)Java 虛擬機棧內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java11中基于嵌套關(guān)系的訪問控制優(yōu)化詳解
Java(和其他語言)通過內(nèi)部類支持嵌套類,要使其正常工作,需要編譯器執(zhí)行一些技巧,下面這篇文章主要給大家介紹了關(guān)于Java11中基于嵌套關(guān)系的訪問控制優(yōu)化的相關(guān)資料,需要的朋友可以參考下2022-01-01
java使用異或?qū)崿F(xiàn)變量互換和異或加密解密示例
這篇文章主要介紹了使用異或?qū)崿F(xiàn)變量互換和異或加密解密示例,需要的朋友可以參考下2014-02-02
Java性能工具JMeter實現(xiàn)上傳與下載腳本編寫
性能測試工作中,文件上傳也是經(jīng)常見的性能壓測場景之一,那么 JMeter 文件上傳下載腳本怎么做,本文詳細的來介紹一下,感興趣的可以了解一下2021-07-07
java字符串比較獲取字符串出現(xiàn)次數(shù)的示例
java獲取一個字符串在整個字符串出現(xiàn)的次數(shù),下面寫出我的思路和二個實現(xiàn)方法,大家參考使用吧2014-01-01

