java虛擬機管理這塊內(nèi)存,所以我們也叫運行時數(shù)據(jù)區(qū)域
總覽
這里按線程是否共享來分類,所謂線程不共享就是每個線程里面都會配一套 程序計數(shù)器 棧, 互相不干涉。
而方法區(qū)和堆是線程所有共享 意味著只有一個(這里注意堆是實際概念 方法區(qū)是一個虛擬概念)
程序計數(shù)器
注意:程序計數(shù)器記錄字節(jié)碼的內(nèi)存地址,這個內(nèi)存地址是怎么來的?
在前幾篇中 字節(jié)碼通過 .class文件 由類加載器 加載到方法區(qū)中(在解析那一步 將引用地址替換成堆內(nèi)存里面的內(nèi)存地址)
如下:
字節(jié)碼中每一行都用地址標(biāo)識,程序計數(shù)器就像是一個地址指示器,告訴執(zhí)行程序 下一行去執(zhí)行哪里。
java虛擬機的多線程是線程輪流切換 并分配處理器執(zhí)行時間的方式來實現(xiàn)的,在任何一個確定的時刻,處理器只會執(zhí)行一條線程中的指令。 所以 為了線程切換后能恢復(fù)到正常位置 每個線程都需要一個獨立的程序計數(shù)器,這就是為什么 程序計數(shù)器不能像堆 方法區(qū)那樣 多線程共享
這篇博客的讀者 一定要理解透這一點。
棧
java虛擬機棧
棧這個數(shù)據(jù)結(jié)構(gòu)是個單向的,你可以把它想象成一個豎著的一邊開口的箱子。它是先進后出。
看上圖的Demo: main 調(diào)用a , a調(diào)用b ,b調(diào)用c。
那么在棧里面就是 mian 先入棧,后面依次是 a b c 入棧, 然后c先被執(zhí)行完 執(zhí)行完之后 c 出棧,后面 b a main 依次出棧。
這個時候新手可能會蒙蔽一下:a 調(diào)用 b 不是a先執(zhí)行嗎? 這里要注意,執(zhí)行b方法 這個過程是 執(zhí)行a方法中的一部分,a調(diào)用b的時候a開始執(zhí)行 但是沒執(zhí)行完 b執(zhí)行完之后 還在a的方法里面 再往下走 a才執(zhí)行完
上面就是方法執(zhí)行過程中棧的邏輯,每執(zhí)行一個方法 就是一個棧內(nèi)部棧幀入棧和出棧的過程。
然后我們來學(xué)習(xí)一下 java虛擬機棧內(nèi)部一個棧幀由哪些組成:
局部變量表:
局部變量表里面存放著,運行過程中所有的局部變量,我們知道 每執(zhí)行一個方法就會創(chuàng)建一個棧幀,那么這個方法里面的局部變量自然要存入棧幀里面,所以在棧幀里面就創(chuàng)建一個局部變量表來專門存儲這些局部變量,方法結(jié)束 棧幀也就出棧結(jié)束了。
順便說一句 一個方法一般都會有 方法參數(shù),參數(shù)變量也會存在這里。
操作數(shù)棧:
操作數(shù)棧你可以把它理解成一個臨時存放數(shù)據(jù)的區(qū)域,虛擬機在執(zhí)行字節(jié)碼指令的時候 需要把一些數(shù)據(jù)臨時存起來備用,
比如我們交換 a和 b的值 在計算機里面 你需要把a的值先臨時放到某個地方 然后把b的值給a 再從那個臨時存放點 把a的值拿出來給b
這種執(zhí)行指令時留的一點余地 就是操作數(shù)棧的作用
幀數(shù)據(jù):
幀數(shù)據(jù)不同的虛擬機有差異
這里面最主要的需要了解的兩個:
- 動態(tài)鏈接:在字節(jié)碼指令中,一個類可能需要調(diào)用其他類的方法或者屬性,這時候就需要用動態(tài)鏈接 用一個映射把其他類的方法信息引進來
- 方法出口:上面說過一個方法執(zhí)行完 就是一個棧彈出的過程,但是彈出以后 虛擬機會疑惑 此時線程執(zhí)行到哪里了?? 這里就需要在方法出口中記錄方法執(zhí)行完后 下一步的位置信息。
本地方法棧
本地方法棧和虛擬機棧發(fā)揮的作用很相似,只不過虛擬棧針對的是java代碼編譯后的字節(jié)碼文章來源:http://www.zghlxwxcb.cn/news/detail-800248.html
本地方法棧針對的是 虛擬機本身的底層已經(jīng)編寫好的 native 方法。文章來源地址http://www.zghlxwxcb.cn/news/detail-800248.html
到了這里,關(guān)于JVM內(nèi)存模型/運行時數(shù)據(jù)區(qū)域的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!