《深入理解Java虛擬機》讀書筆記1--Java內存區域

《深入理解Java虛擬機》是我個人讀過的第一本關于JVM方面的書籍。十分有幸能夠讀到這本書,在此對作者表示深刻的敬意

不知道有沒有人和我一樣有類似的情況,就是一本書讀完,經過一段時間之后,林林總總最后留在腦子里的并不多,很多東西又還給了作者。有人可能會說,之所以會遺忘,是因為你根本沒有理解。我并不否認這點,說實話,很多書讀過一遍之后都會存在沒有讀懂的部分。但是隨著我們閱歷的豐富以及期間不斷的學習,過去不懂的部分終究會慢慢讀懂。鑒于這種情況,我覺得讀書筆記還是很有必要:讀書期間總結歸納,日后溫故知新

筆記僅僅是我個人對此書的一份總結,提綱挈領。如需了解細節,請完整閱讀原著,這本書我個人也強烈推薦。下面,開始《深入理解Java虛擬機》讀書筆記的第一篇--Java內存區域

運行時數據區域

JVM在運行Java程序時將內存區域劃分為不同的部分,這些區域有各自的用途以及各自的內存管理策略

在Java虛擬機的概念模型中,這些區域大致可以分為:程序計數器(Program Counter Register)、虛擬機棧(VM Stack)、本地方法棧(Native Method Stack)、堆(Heap)、方法區(Method Area)

其中前三者是線程隔離的內存區域,后兩者是線程共享的內存區域

1.程序計數器

程序計數器可以簡單理解為線程執行字節碼的行號指示器。由于在線程切換后需要恢復到程序的執行位置,因此每個線程都有各自的程序計數器

2.虛擬機棧

虛擬機棧描述的是Java方法執行的內存模型,方法在執行的時候會創建棧幀。棧幀用于存儲方法執行時所需的局部變量表、操作數棧、動態鏈接、方法出口等信息。方法的執行伴隨著棧幀在虛擬機棧中的入棧及出棧

局部變量表存儲了基本數據類型、對象引用、返回地址

Java虛擬機規范對此區域規定了兩種異常情況:當線程請求的棧深度大于虛擬機允許的最大深度將觸發StackOverflowError;如果虛擬機棧在動態擴展時無法申請到足夠的內存將觸發OutOfMemoryError

3.本地方法棧

本地方法棧與虛擬機棧作用類似,區別在于虛擬機棧用于Java方法執行,而本地方法棧用于本地方法執行

有些虛擬機甚至不區分本地方法棧和虛擬機棧,而是將它們合二為一

同樣本地方法棧也會觸發StackOverflowError和OutOfMemoryError

4.堆

堆用于存放對象實例,可以細分為新生代和老年代,進一步可以細分為Eden空間、From Survivor空間、To Survivor空間等。進一步細分區域的目的是根據對象的特征更好的分配以及回收內存空間

堆在物理上可以是不連續的空間,只要在邏輯上是連續的即可。如果當前堆內存已經用完并且無法動態擴展的時候會觸發OutOfMemoryError

5.方法區

方法區主要用于存放已經被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據

運行時常量池是方法區的一部分,主要用于存放編譯期生成的字面量和符號引用,另外在運行時也可以將新的常量加入池中

這個區域的內存回收通常收益較低,主要是針對常量池的回收以及對類型的卸載(對類型卸載的要求十分嚴苛)

同樣,當方法區無法滿足內存分配需求時,將會觸發OutOfMemoryError

6.直接內存

直接內存并非Java虛擬機規范中定義的內存區域,但是在大量使用NIO的程序中有可能觸發OutOfMemoryError異常

NIO基于Channel和Buffer,可以直接使用本地方法分配堆外內存,然后通過存儲在堆中的DirectByteBuffer對象作為這塊堆外內存的引用進行操作。雖然堆外內存不會受到Java堆大小的限制,但是仍然會受制于物理內存以及操作系統的限制。當各內存區域總和大于物理內存或者達到操作系統限制,從而導致動態擴展時觸發OutOfMemoryError

對象探秘

不同的虛擬機,對于對象的創建、布局和訪問會有所差異,下面僅以HotSpot的堆內存為例進行介紹

1.對象的創建

#類檢查及類加載

虛擬機在遇到new指令的時候,首先會去常量池檢查類的符號引用,如果發現沒有對此類進行加載、解析、初始化,那么首先會對該類進行加載

#內存分配

之后虛擬機會為該對象分配內存。由于對象所需內存在類加載后就可以確定,因此分配內存實際上就是從未使用的堆內存中劃分出一塊確定大小的存儲空間。此過程有兩種方式:

1)對于規整的堆內存,直接將指針向空閑一側移動所需的大小,這種方式叫做“指針碰撞”

2)對于不規整對堆內存,虛擬機會維護一個空閑內存列表,當需要分配內存時,劃分出一塊足夠的空間并且更新空閑列表,這種方式叫做“空閑列表”

至于堆內存是否規整連續,取決于具體的垃圾收集器(主要取決于是否帶有compact功能)

由于對象的創建是一個十分頻繁的過程,在并發情況下會有并發安全的問題。解決的方式有兩種:

1)對內存分配進行同步處理,實際上虛擬機采用CAS的方式保證原子性

2)另一種方式是把內存分配的動作按照線程進行隔離,即每個線程會預先分配一小塊內存,稱為本地線程分配緩沖(Thread Local Allocation Buffer,TLAB)。只有在TLAB用完需要新分配的時候在采取同步處理

#初始化零值

內存分配完畢后,虛擬機會對該內存區域初始化零值,如果是TLAB方式,這一步可以提前到TLAB階段。這一步保證了對象實例屬性的初始化。這也就是為什么對象的實例屬性可以不賦初值就能夠直接訪問

#對象頭設置

接下來,虛擬機需要將對象進行一些設置,將類的元數據、哈希碼、GC分代信息等設置到對象頭中

#對象初始化

執行完上述步驟后,對象的實例屬性還都是零值,下面會執行<init>方法,按照程序的意圖對對象進行初始化(我的理解是執行構造方法)。之后在將對象的引用入棧。至此,對象的創建過程結束

2.對象的內存布局

在HotSpot虛擬機當中,對象的內存布局分為三個區域:對象頭、實例數據、對齊填充

#對象頭

對象頭主要存儲兩部分信息,一部分是對象的運行時數據(如哈希碼、GC分代信息、鎖狀態標志、線程持有的鎖、偏向線程ID、偏向時間戳等),另一部分是類型指針(即指向類元數據的指針,代表該對象是哪個類的實例。當然類的元數據也并不一定要存儲在對象頭,這個后續再討論)

#實例數據

實例數據部分用于存儲對象實例的數據,即實例屬性的內容,父類的屬性也會記錄下來。存儲順序會受到虛擬機的分配策略以及字段的定義順序的影響。默認的分配策略大致有幾點規則:

1)會將相同寬度的屬性分配在一起

2)滿足1的前提下,父類中的屬性出現在子類前

3)CompactFields參數為true的時候,會將子類中寬度較窄的屬性插入到父類屬性的空隙之中

#對齊填充

由于HotSpot虛擬機要求對象的其實地址必須是8字節的整數倍,因此對于對象大小不是8字節整數倍的對象,會被對齊填充

3.對象的訪問定位

對象的訪問解決的是如何通過棧中對象的引用訪問到堆中實際對象的問題,目前主流的方式有兩種:

1)句柄訪問,棧中對象的引用存儲的是對象的句柄地址(句柄在句柄池中維護),句柄存儲了堆中對象實例的地址以及方法區中對象的類型數據的地址。

這種方式的優點是引用中存儲的是穩定的句柄,當對象地址變化的時候(GC過程中可能會移動對象實例),只需要更新句柄,不需要更新引用;缺點也顯而易見,訪問對象時多一次指針操作

2)直接指針訪問,棧中對象的引用存儲的就是對象實例的地址,對象實例(對象頭)中又存儲了方法區中對象的類型數據的地址

這種方式的優點就是訪問迅速(比前者少一次指針操作),在HotSpot虛擬機中采用此種方式

思維導圖:

筆記1結束

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

推薦閱讀更多精彩內容

  • 就在昨天,老媽和我微信視頻,說:聽說你買了一輛車。可不是嗎?我終于買了一輛自行車。哈哈哈哈,兩人不約大笑。 我買了...
    木木木俠閱讀 973評論 0 4
  • 金燦燦的玉米囤滿農家的庭院 紅通通的小棗晾曬在屋前院后 黑黝黝的豆兒裝好袋子聚在屋檐下 豐收!今年的秋,農家院落顯...
    豐盈倉廩閱讀 854評論 0 0
  • 寒風凜冽,寒氣襲人,枯草蕭疏,綠色盡失,今年的冬天如此蒼白凄涼且冷漠. M點燃一支煙,吞云吐霧起來,一圈圈的煙霧,...
    幽谷泉涌閱讀 867評論 0 1
  • 01 大熊和小琪是大學同學,也是我認識的人里,唯一一對畢業季在一起,結果談了三年異地戀的戀人。 上周末,大熊還是失...
    子小洛閱讀 3,844評論 47 61