最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

Java虛擬機-對象(HotSpot)

2020-10-01 18:53 作者:bili_93709487  | 我要投稿

對象的創(chuàng)建

當虛擬機遇到一條new指令時,首先將去檢查這個指令的參數(shù)是否能在常量池中定位到一個類的符號引用,并且檢查這個符號引用代表的類是否已經被加載、解析和初始化過。如果沒有就應先執(zhí)行相應的類加載過程。

在類加載檢查通過后,接下來虛擬機將為新生對象分配內存。對象所需的內存大小,在類加載完成后便可以完全確定。

為對象分配空間的方式總共有兩種,指針碰撞(Bump the Pointer)空閑列表(?Free List)。選擇哪種分配方式由Java堆是否規(guī)整決定,Java堆是否規(guī)整又由所采用的垃圾收集器是否帶有壓縮整理(Compact)功能決定。采用Serial、ParNew等帶有壓縮整理過程的收集器時,系統(tǒng)采用的分配算法是指針碰撞;而使用CMS這種基于Mark-Sweep算法的收集器時,理論上只能采用復雜的空閑列表來分配內存(CMS為了能在多數(shù)的情況下分配的更快,設計了一個叫做Linear Allocation Buffer的分配緩沖區(qū),通過空閑列表拿到一大塊分配緩沖區(qū)后,里面仍舊可以采用指針碰撞來分配內存)。

分配內存在并發(fā)情況下并不是線程安全的。解決這個問題的方法有兩種:

CAS: CAS 是樂觀鎖的一種實現(xiàn)方式。所謂樂觀鎖就是,每次不加鎖而是假設沒有沖突而去完成某項操作,如果因為沖突失敗就重試,直到成功為止。虛擬機采用 CAS 配上失敗重試的方式保證更新操作的原子性。

TLAB: 為每一個線程預先分配一塊內存,虛擬機在給線程中的對象分配內存時,首先在TLAB分配,當對象大于TLAB中的剩余內存或TLAB的內存已用盡時,再采用上述的CAS為新的TLAB進行內存分配。

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

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


初始化對象

內存分配完畢后,虛擬機需要將分配到的內存空間初始化為零值(不包括對象頭),如果使用TLAB,初始化工作可以提前到TLAB分配時進行。這一步保證了Java對象的實例在Java代碼中不賦初值就能使用。

接下來虛擬機要對對象進行必要的設置,例如這個對象是哪個類的實例、如何才能找到類的元數(shù)據信息,對象的哈希碼(實際上對象哈希碼會延后到真正調用Object::hashCode()時才會計算),對象的GC分代年齡等信息。此時對于虛擬機來說,一個新的對象實例已經誕生了。

在這之后(new指令完成),會執(zhí)行構造函數(shù)------即Class文件中的<init>方法,把對象按照程序員的意愿進行初始化,此時一個真正可用的對象才算完全產生。

對象的內存布局

對象在內存中可以分為三塊區(qū)域:對象頭(Header)、實例數(shù)據(Instance data)對齊補充(Padding)。

HotSpot VM的對象頭包括兩部分信息,第一部分用于存儲對象自身的運行數(shù)據,如哈希碼、GC分代年齡、鎖狀態(tài)標志、線程持有的鎖、偏向線程ID、偏向時間戳等。這部分數(shù)據長度在32位和64位(未開啟壓縮指針)的虛擬機中分別為32bit和64bit,官方稱它為”Mark Word“。對象頭的另一部分是類型指針,即對象指向它類元數(shù)據的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例。另外,如果對象是Java數(shù)組,那在對象頭中還必須有一塊用于記錄數(shù)組長度的數(shù)據。

實例數(shù)據部分是對象真正存儲的有效信息,也是程序代碼中所定義的各種類型的字段內容。這部分的存儲順序會受到虛擬機分配策略參數(shù)和字段在Java源碼中的順序影響。HotSpot虛擬機默認的分配策略為longs/doubles、ints、shorts/chars、bytes/booleans、oops(Ordinary Object Pointers)。在滿足這個條件的前提下,在父類中定義的變量會在子類前面。如果-XX:CompactFields參數(shù)值為true(默認為true),那么子類中較窄的變量也可能會插入到父類變量的空隙中以節(jié)省空間。

對齊填充并不是必然存在的,也沒有特殊含義,它僅僅起著占位符的作用。由于HotSpot VM的自動內存管理系統(tǒng)要求任何對象起始地址必須為8字節(jié)的整數(shù)倍,也就是對象大小必須為8字節(jié)整數(shù)倍,而對象頭正好是8字節(jié)的倍數(shù)(1/2倍),因此,對象實例部分沒有對齊時,就需要通過對齊填充來補全。

對象的訪問

對象建立之后就是為了使用,Java程序通過棧上的reference數(shù)據來操作對象。reference只是對象的引用,Java虛擬機規(guī)范也沒有規(guī)定應該通過何種方式去定位對象。現(xiàn)在主流的訪問方式是使用句柄直接指針。

如果使用句柄訪問的方式,那么Java堆中會劃分出一塊內存來作為句柄池,reference存儲的就是句柄地址,句柄中包含了對象實例數(shù)據和類型數(shù)據的地址信息。

使用句柄


如果使用直接指針的方式,reference中存放的就是對象實例的地址。

直接指針

使用句柄的好處是reference中存放的是穩(wěn)定的句柄地址,在對象被移動后,reference的值無需改變;直接指針的好處是速度更快,它節(jié)省了一次指針定位的時間。HotSpot使用的是直接指針的方式。(也有例外情況,如果使用了Shenandoah收集器的話也會有一次額外的轉發(fā))


Java虛擬機-對象(HotSpot)的評論 (共 條)

分享到微博請遵守國家法律
永康市| 广丰县| 福泉市| 克什克腾旗| 青海省| 六盘水市| 商都县| 德安县| 阿勒泰市| 丰城市| 郑州市| 浮山县| 蒙城县| 济宁市| 玛多县| 甘南县| 三门峡市| 桂平市| 延安市| 甘德县| 贵溪市| 木兰县| 宁晋县| 永清县| 泸西县| 华容县| 博兴县| 阳泉市| 城步| 丰都县| 开化县| 西吉县| 荔浦县| 黄山市| 武清区| 湟中县| 浏阳市| 类乌齐县| 林州市| 阿图什市| 蕲春县|