JVM筆記(一)
JVM執行時的資料區域
@Date:2018-5-16
@Author:LF
接下來則分塊理解各個區域的作用
pc暫存器(程式計數器)–執行緒私有
程式計數器感覺比較類似於廣義上的暫存器。那麼問題來了:
寄存什麼?
- 答:寄存指令
什麼指令?
- 答:當前執行緒正在執行的方法所對應的位元組碼的指令
為什麼要記錄這個指令?計數器存在的意義是什麼?
- 答:為了針對多執行緒的程式。JVM的多執行緒實際上是通過執行緒輪流切換分配處理器時間實現,為了區分每一個方法當前執行的是什麼就需要一個東西儲存執行緒當前時刻在幹什麼,這樣可以保證線上程切換後可以繼續執行之前停止前正在執行的指令。
JVM棧(VM Stack)–執行緒私有
棧幀與執行緒中的方法對應,一個方法就會有一個對應的棧幀。棧幀中儲存方法的所有資訊。因為棧的先進後出的性質,故在方法中呼叫其他方法時,心得方法棧幀入棧作為當前棧幀(棧頂幀),方法結束時則從方法裡向外結束,棧幀依次出棧。
1.區域性變量表
基本單位:容量槽(slot),一個slot無明確的大小,但是每個slot都能存放下java的8種基本資料。
區域性變量表的實質是一片儲存空間,用來儲存方法引數和方法內部定義的區域性變數。
JVM通過索引的方式訪問區域性變量表
slot的複用特性:
- 當方法中的變數作用域結束而方法還未完全結束時,此刻其實前面的變數已經不會再用到了,因為變數作用域已經結束了嘛,所以其slot可以騰出來給其他變數使用,這就是slot的複用特性。目的是為了節省棧空間。
2.運算元棧
方法執行時,會有各種位元組碼指令往運算元棧中寫入或讀出內容。也就是說運算元棧是用來存放一些值的。
如果說區域性變量表理解為方法內所有引數和定義的區域性變數的儲存空間,那麼運算元棧則是方法執行時候的各個值的儲存空間或者說是緩衝空間,感覺作用和PC計數器差不多。
3.動態連結
每個棧幀都包含一個指向執行時常量池中該棧幀所屬方法的引用。這就叫動態連結。
如何理解這句話?
在方法執行中,當需要另一個方法被呼叫時,其實就是在當前方法中使用了被呼叫方法在執行時常量的引用。該引用指向被呼叫方法棧幀,通過該引用將棧幀入JVM棧。
也就是說可以把動態連結理解為一種繫結標記,和執行時常量池中對該方法的符號引用進行標記。我是這麼理解的。
執行時常量池中的符號引用會有兩種繫結方式(方法的繫結)。簡單來說,當類載入階段可以確定的方法(比如不存在過載),即可以在類載入時將符號引用直接轉化為直接引用,這就叫做靜態解析。
但是如果遇到在類載入時候無法確定被呼叫的目標方法(比如存在過載,根據具體的方法引數確定是呼叫哪個方法的時候),必須通過執行時確定呼叫的方法,確定後才將符號引用轉化為直接引用,這就叫做動態連結。
動態連結的存在解決的就是在執行時將符號引用轉化為直接引用的問題。
4.方法返回值
顧名思義,方法返回值儲存的就是當前方法的返回值,當前方法結束後,棧幀出戰,其返回值會被壓入當前棧幀的運算元棧。應該是比較好理解的。
本地方法棧(Native Method Stack)–執行緒私有
用於支援本地方法,即非java方法,其作用與JVM棧類似,很多虛擬機器(如Sun公司的HotSpot)會將這兩種棧合二為一。
Java堆(Java heap)–執行緒共享
唯一作用:存放物件例項
但是並不是所有物件都放在Java堆上
而且Java堆的記憶體不連續,是GC(garbage collection)重點回收物件
其實說白了,就是java執行時的堆空間嘛。
方法區–執行緒共享
用來儲存已經被JVM載入的類資訊、常量、靜態變數等。和java堆一樣擁有不連續的記憶體區域。而且執行時常量池就屬於方法區。