JVM學習筆記3運行時數據區(qū)(虛擬機棧)

虛擬機棧

棧管運行,堆管存儲
即:棧解決程序的運行問題,即程序如何執(zhí)行,或者說如何處理數據。堆解決的是數據存儲的問題,即數據怎么放、放在哪兒。

背景:

由于跨平臺性的設計,Java的指令都是根據棧來設計的。不同平臺CPU架構不同,所以不能設計為基于寄存器的。
優(yōu)點是跨平臺,指令集小,編譯器容易實現(xiàn),缺點是性能下降,實現(xiàn)同樣的功能需要更多的指令。

Java虛擬機棧是什么?

Java虛擬機棧(Java Virtual Machine Stack) ,早期也叫Java棧。每個線程在創(chuàng)建時都會創(chuàng)建一-個虛擬機棧,其內部保存一個個的棧幀(Stack Frame) ,對應著一次次的Java方法調用。
?是線程私有的

生命周期

生命周期和線程一致。

作用

主管Java程序的運行,它保存方法的局部變量、部分結果,并參與方法的調用和返回。

棧的特點(優(yōu)點)

●?棧是一種快速有效的分配存儲方式,訪問速度僅次于程序計數器。
●?JVM直接對Java棧的操作只有兩個:
???每個方法執(zhí)行,伴隨著進棧(入棧、壓棧)
???執(zhí)行結束后的出棧工作
●?對于棧來說不存在垃圾回收問題


棧中可能出現(xiàn)的異常

●Java虛擬機規(guī)范允許Java棧的大小是動態(tài)的或者是固定不變的
???如果采用固定大小的Java虛擬機棧,那每一個線程的Java虛擬機棧容量可以在線程創(chuàng)建的時候獨立選定。如果線程請求分配的棧容量超過Java虛擬機棧允許的最大容量,Java 虛擬機將會拋出一個StackOverflowError異常。
???如果Java虛擬機棧可以動態(tài)擴展,并且在嘗試擴展的時候無法申請到足夠的內存,或者在創(chuàng)建新的線程時沒有足夠的內存去創(chuàng)建對應的虛擬機棧,那Java虛擬機將會拋出一個OutOfMemoryError異常。

棧中存儲的是什么?

●?每個線程都有自己的棧,棧中的數據都是以棧幀(Stack Frame)的格式存在。
●?在這個線程上正在執(zhí)行的每個方法都各自對應一個棧幀(Stack Frame) 。
●?棧幀是一個內存區(qū)塊,是一個數據集,維系著方法執(zhí)行過程中的各種數據信息。

棧的運行原理

●?JVM直接對Java棧的操作只有兩個,就是對棧幀的壓棧出棧遵循“先進后出”/“后進先出”原則
●?在一條活動線程中,一個時間點上,只會有一個活動的棧幀。即只有當前正在執(zhí)行的方法的棧幀(棧頂棧幀)是有效的,這個棧幀被稱為當前棧幀(Current Frame) ,與當前棧幀相對應的方法就是當前方法(Current Method),定義這個方法的類就是當前類(Current Class)
執(zhí)行引擎運行的所有字節(jié)碼指令只針對當前棧幀進行操作。
●?如果在該方法中調用了其他方法,對應的新的棧幀會被創(chuàng)建出來,放在棧的頂端,成為新的當前幀。


●?不同線程中所包含的棧幀是不允許存在相互引用的,即不可能在一個棧幀之中引用另外一個線程的棧幀。
●?如果當前方法調用了其他方法,方法返回之際,當前棧幀會傳回此方法的執(zhí)行結果給前一個棧幀,接著,虛擬機會丟棄當前棧幀,使得前一個棧幀重新成為當前棧幀。
●?Java方法有兩種返回函數的方式,一種是正常的函數返回,使用return指令、另外一種是拋出異常。。

相關面試題目

●?舉例棧溢出的情況?
???StackOverflowError,通過-Xss設置棧的大小,
●?調整棧大小,就能保證不出現(xiàn)溢出嗎?
???不能,理論上來說死循環(huán)只能讓StackOverflowError出現(xiàn)的更晚一些,就像給你100塊錢和1000塊錢。只能保證你多用點兒時間
●?分配的棧內存越大越好嗎?
???并不是,越大能降低一定時間內出現(xiàn)StackOverflowError的概率,內存空間是有限的,越大會擠占其他空間,會導致線程數變少
●?垃圾回收是否會涉及到虛擬機棧?
???不會,存在Error,不存在GC,就是入棧出棧
●?方法中定義的局部變量是否線程安全?
???具體問題具體分析,如果實在方法內創(chuàng)建的是線程安全的,如果是作為參數傳入的可能就是線程不安全的,如果內部定義,返回出去的話,也是有可能是不安全的


棧幀

==可使用idea的jclasslib插件輔助查看==

內部結構

每個棧幀中存儲著:
●?局部變量表(Local Variables)
???局部變量表也被稱之為局部變量數組或本地變量表
???定義為一個數字數組,主要用于存儲方法參數和定義在方法體內的局部變量,這些數據?類型包括各類基本數據類型、對象引用(reference) ,以及returnAddress類型
???由于局部變量表是建立在線程的棧上,是線程的私有數據,因此不存在數據安全問題
???局部變量表所需的容量大小是在編譯期確定下來的,并保存在方法的Code屬性的maximum local variables數據項中。在方法運行期間是不會改變局部變量表的大小的。
●?操作數棧(Operand Stack) ( 或表達式棧(Expression Stack),后進先出(Last-In-First-Out)),說直白點就是臨時存儲空間
???操作數棧,在方法執(zhí)行過程中,根據字節(jié)碼指令,往棧中寫入數據或提取數據,即入棧(push) /出棧(pop)
???某些字節(jié)碼指令將值壓入操作數棧,其余的字節(jié)碼指令將操作數取出棧。使用它們后再把結果壓入棧。比如:執(zhí)行復制、交換、求和等操作
???下圖中bipush,iload,iadd都會涉及到操作數棧入棧,istore會涉及到從操作數棧中出棧

public void testAddOperation() {
  byte i = 15;
  int j = 8;
  int k = i + j;
}




●?動態(tài)鏈接(Dynamic Linking) ( 或指向運行時常量池的方法引用)
???每一個棧幀內部都包含一個指向運行時常量池(Constant Pool)該棧幀所屬方法的引用包含這個引用的目的就是為了支持當前方法的代碼能夠實現(xiàn)動態(tài)鏈接(Dynamic Linking) 。比如: invokedynamic指 令
???在Java源文件被編譯到字節(jié)碼文件中時,所有的變量和方法引用都作為符號引用( symbolic Reference)保存在class文件的常量池里。比如:描述一個方法調用了另外的其他方法時,就是通過常量池中指向方法的符號引用來表示的,那么動態(tài)鏈接的作用就是為了將這些符號引用轉換為調用方法的直接引用

●?方法返回地址(Return Address) (或方法正常退 出或者異常退出的定義)
???存放調用該方法的pc寄存器的值。
??? 一個方法的結束,有兩種方式:正常執(zhí)行完成出現(xiàn)未處理的異常,非正常退出
???無論通過哪種方式退出,在方法退出后都返回到該方法被調用的位置。方法正常退出時,調用者的pc計數器的值作為返回地址,即調用該方法的指令的下一條指令的地址。而通過異常退出的,返回地址是要通過異常表來確定,棧幀中一般般不會保存這部分信息。

●?一些附加信息



關于slot的理解

●?參數值的存放總是在局部變量數組的index0開始,到數組長度-1的索引結束。
●?局部變量表,最基本的存儲單元是Slot (變量槽)
●?局部變量表中存放編譯期可知的各種基本數據類型(8種),引用類型(reference),returnAddress類 型。
●?在局部變量表里,32位以內的類型只占用一個slot (包括returnAddress類型),64位的類型(long和double)占用兩個slot
????byte 、short 、char在存儲前被轉換為int,boolqan 也被轉換為int,0表示false,非0表示true。
????long和double 則占據兩個Slot。
●?JVM會為局部變量表中的每一個slot都分配一個訪問索引,通過這個索引即可成功訪問到局部變量表中指定的局部變量值
●?當一個實例方法被調用的時候,它的方法參數和方法體內部定義的局部變量將會按照順序被復制到局部變量表中的每一個slot上
●?如果需要訪問局部變量表中一個64bit的局部變量值時,只需要使用前一個索引即可。(比如:訪問long或double類型變量)
●?如果當前幀是由構造方法或者實例方法創(chuàng)建的,那么該對象引用this將會存放在index為0的slot處,其余的參數按照參數表順序繼續(xù)排列。

補充說明

●?在棧幀中,與性能調優(yōu)關系最為密切的部分就是前面提到的局部變量表。在方法執(zhí)行時,虛擬機使用局部變量表完成方法的傳遞。
●?局部變量表中的變量也是重要的垃圾回收根節(jié)點,只要被局部變量表中直接或間接引用的對象都不會被回收。

Slot的重復利用

●?棧幀中的局部變量表中的槽位是可以重用的,如果一個局部變量過了其作用域,那么在其作用域之后申明的新的局部變量就很有可能會復用過期局部變量的槽位,從而達到節(jié)省資源的目的。

public void test() {
  int a = 0;
  {
    int b = 0;
    b = a + 1;
  }
  //  c重復利用了b的slot(槽位)
  int c = a + 1;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,517評論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,087評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,521評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,493評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,207評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,603評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,624評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,813評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 49,364評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,110評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,305評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,874評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,532評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,953評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,209評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,033評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,268評論 2 375