日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

你知道JVM内存的那些事吗?

發布時間:2024/4/17 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 你知道JVM内存的那些事吗? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

對于C語言開發的程序員來說,在內存管理方面,必須負責每一個對象的生命周期,從有到無。
對于Java程序員你來說,在虛擬機內存管理的幫助下,不需要為每個new對象都匹配free操作,內存泄露和內存溢出等問題也不太容易出現,不過也正是因為把內存管理交給了虛擬機,一旦運行中的程序出現了內存泄露問題,給排查過程造成很大困難。所以只有理解了Java虛擬機的運行機制,才能夠運籌帷幄于各種代碼。本文以HotSpot為例說說虛擬機的那些事。

JAVA虛擬機把管理的內存劃分為幾個不同的數據區。


Java堆

Java堆是被所有線程共享的一塊內存區域,主要用于存放對象實例,Java虛擬機規范中有這樣一段描述:所有的對象實例和數據都要在堆上進行分配。為對象分配內存就是把一塊大小確定的內存從堆內存中劃分出來,通常有兩種方法實現:

1 、指針碰撞法
假設Java堆中內存時完整的,已分配的內存和空閑內存分別在不同的一側,通過一個指針作為分界點,需要分配內存時,僅僅需要把指針往空閑的一端移動與對象大小相等的距離。

2、空閑列表法
事實上,Java堆的內存并不是完整的,已分配的內存和空閑內存相互交錯,JVM通過維護一個列表,記錄可用的內存塊信息,當分配操作發生時,從列表中找到一個足夠大的內存塊分配給對象實例,并更新列表上的記錄。

對象創建是一個非常頻繁的行為,進行堆內存分配時還需要考慮多線程并發問題,可能出現正在給對象A分配內存,指針或記錄還未更新,對象B又同時分配到原來的內存,解決這個問題有兩種方案:
1、采用CAS保證數據更新操作的原子性;
2、把內存分配的行為按照線程進行劃分,在不同的空間中進行,每個線程在Java堆中預先分配一個內存塊,稱為本地線程分配緩沖(Thread Local Allocation Buffer, TLAB);

Java棧

Java棧是線程私有的,每個線程對應一個Java棧,每個線程在執行一個方法時會創建一個對應的棧幀(Stack Frame),棧幀負責存儲局部變量變量表、操作數棧、動態鏈接和方法返回地址等信息。每個方法的調用過程,相當于棧幀在Java棧的入棧和出棧過程。

局部變量表 用于存放方法參數和方法內部定義的局部變量,其大小在代碼編譯期間已經確定,在方法運行期間不會改變。局部變量表以變量槽(Slot)為最小存儲單位,每個Slot能夠存放一個boolean、byte、char、shot、int、float、reference和returnAddress類型的32位數據,對于64位的數據類型long和double,虛擬機會以高位對齊的方式為其分配兩個連續的Slot空間。

在方法執行時,如果是實例方法,即非static方法,局部變量表中第0位Slot默認存放對象實例的引用,在方法中可以通過關鍵字 this 進行訪問,方法參數按照參數列表順序,從第1位Slot開始分配,方法內部變量則按照定義順序進行分配其余的Slot。

class?test?{public?int?calc(int?a,?int?b,?String?operation)?{operation?=?"+";????????return??a?+?b;}????public?void?main(String?args[])?{calc(100,?200,?"+");} }

對應的局部變量表如下:



使用 javap -c 命令查看方法calc的字節碼


其中iload_1和iload_2分別從局部變量表中的第1位和第2位中加載數據。

方法區

方法區和Java堆一樣,是所有線程共享的內存區域,用于存放已被虛擬機加載的類信息、常量、靜態變量和即時編譯器編譯后的代碼等數據。
運行時常量池是方法區的一部分,用于存放編譯期間生成的各種字面常量和符號引用。

指令計數器

指令計數器是線程私有的,每個線程都有獨立的指令計數器,計數器記錄著虛擬機正在執行的字節碼指令的地址,分支、循環、跳轉、異常處理和線程恢復等操作都依賴這個計數器完成。如果線程執行的是native方法,這個計數器則為空。

對象的內存布局

對象在內存中布局可以分成三塊區域:對象頭、實例數據和對齊填充。
1、對象頭
對象頭包括兩部分信息:運行時數據和類型指針,如果對象是一個數組,還需要一塊用于記錄數組長度的數據。

1.1、運行時數據包括哈希碼(HashCode)、GC分代年齡、鎖狀態標志、線程持有的鎖、偏向鎖ID和偏向時間戳等,這部分數據在32位和64位虛擬機中的長度分別為32bit和64bit,官方稱為"Mark Word"。Mark Word被設計成非固定的數據結構,以實現在有限空間內保存盡可能多的數據。
32位的虛擬機中,對象未被鎖定的狀態下,Mark Word的32bit中25bit存儲對象的HashCode、4bit存儲對象分代年齡、2bit存儲鎖標志位、1bit固定為0,具體如下:



其它狀態(輕量級鎖定、重量級鎖定、GC鎖定、可偏向鎖)下Mark Word的存儲內容如下:



1.2、對象頭的類型指針指向該對象的類元數據,虛擬機通過這個指針可以確定該對象是哪個類的實例。

2、實例數據
實例數據就是在程序代碼中所定義的各種類型的字段,包括從父類繼承的,這部分的存儲順序會受到虛擬機分配策略和字段在源碼中定義順序的影響。
3、對齊填充
由于HotSpot的自動內存管理要求對象的起始地址必須是8字節的整數倍,即對象的大小必須是8字節的整數倍,對象頭的數據正好是8的整數倍,所以當實例數據不夠8字節整數倍時,需要通過對齊填充進行補全。



轉載于:https://blog.51cto.com/14028890/2409623

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的你知道JVM内存的那些事吗?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。