最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入理解JVM之Java對象的創(chuàng)建、內(nèi)存布局、訪問定位詳解

 更新時間:2019年09月15日 11:10:31   作者:smile4lee  
這篇文章主要介紹了深入理解JVM之Java對象的創(chuàng)建、內(nèi)存布局、訪問定位,結(jié)合實例形式詳細(xì)分析了Java對象的創(chuàng)建、內(nèi)存布局、訪問定位相關(guān)概念、原理、操作技巧與注意事項,需要的朋友可以參考下

本文實例講述了深入理解JVM之Java對象的創(chuàng)建、內(nèi)存布局、訪問定位.分享給大家供大家參考,具體如下:

對象的創(chuàng)建

一個簡單的創(chuàng)建對象語句Clazz instance = new Clazz();包含的主要過程包括了類加載檢查、對象分配內(nèi)存、并發(fā)處理、內(nèi)存空間初始化、對象設(shè)置、執(zhí)行ini方法等。

主要流程如下:

java對象創(chuàng)建流程

1. 類加載檢查

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

2. 對象分配內(nèi)存

對象所需內(nèi)存的大小在類加載完成后便完全確定(對象內(nèi)存布局),為對象分配空間的任務(wù)等同于把一塊確定大小的內(nèi)存從Java堆中劃分出來。

根據(jù)Java堆中是否規(guī)整有兩種內(nèi)存的分配方式:(Java堆是否規(guī)整由所采用的垃圾收集器是否帶有壓縮整理功能決定)

  • 指針碰撞(Bump the pointer)
    Java堆中的內(nèi)存是規(guī)整的,所有用過的內(nèi)存都放在一邊,空閑的內(nèi)存放在另一邊,中間放著一個指針作為分界點的指示器,分配內(nèi)存也就是把指針向空閑空間那邊移動一段與內(nèi)存大小相等的距離。例如:Serial、ParNew等收集器。
  • 空閑列表(Free List)
    Java堆中的內(nèi)存不是規(guī)整的,已使用的內(nèi)存和空閑的內(nèi)存相互交錯,就沒有辦法簡單的進(jìn)行指針碰撞了。虛擬機(jī)必須維護(hù)一張列表,記錄哪些內(nèi)存塊是可用的,在分配的時候從列表中找到一塊足夠大的空間劃分給對象實例,并更新列表上的記錄。例如:CMS這種基于Mark-Sweep算法的收集器。

3. 并發(fā)處理

對象創(chuàng)建在虛擬機(jī)中時非常頻繁的行為,即使是僅僅修改一個指針指向的位置,在并發(fā)情況下也并不是線程安全的,可能出現(xiàn)正在給對象A分配內(nèi)存,指針還沒來得及修改,對象B又同時使用了原來的指針來分配內(nèi)存的情況。

  • 同步
    虛擬機(jī)采用CAS配上失敗重試的方式保證更新操作的原子性
  • 本地線程分配緩沖(Thread Local Allocation Buffer, TLAB)
    把內(nèi)存分配的動作按照線程劃分為在不同的空間之中進(jìn)行,即每個線程在Java堆中預(yù)先分配一小塊內(nèi)存(TLAB)。哪個線程要分配內(nèi)存,就在哪個線程的TLAB上分配。只有TLAB用完并分配新的TLAB時,才需要同步鎖定。

4. 內(nèi)存空間初始化

虛擬機(jī)將分配到的內(nèi)存空間都初始化為零值(不包括對象頭),如果使用了TLAB,這一工作過程也可以提前至TLAB分配時進(jìn)行。

內(nèi)存空間初始化保證了對象的實例字段在Java代碼中可以不賦初始值就直接使用,程序能訪問到這些字段的數(shù)據(jù)類型所對應(yīng)的零值。

注意:類的成員變量可以不顯示地初始化(Java虛擬機(jī)都會先自動給它初始化為默認(rèn)值)。方法中的局部變量如果只負(fù)責(zé)接收一個表達(dá)式的值,可以不初始化,但是參與運(yùn)算和直接輸出等其它情況的局部變量需要初始化。

5. 對象設(shè)置

虛擬機(jī)對對象進(jìn)行必要的設(shè)置,例如這個對象是哪個類的實例、如何才能找到類的元數(shù)據(jù)信息、對象的哈希碼、對象的GC分代年齡等信息。這些信息存放在對象的對象頭之中。

6. 執(zhí)行init()

在上面的工作都完成之后,從虛擬機(jī)的角度看,一個新的對象已經(jīng)產(chǎn)生了。但是從Java程序的角度看,對象的創(chuàng)建才剛剛開始init()方法還沒有執(zhí)行,所有的字段都還是零。

所以,一般來說(由字節(jié)碼中是否跟隨invokespecial指令所決定),執(zhí)行new指令之后會接著執(zhí)行init()方法,把對象按照程序員的意愿進(jìn)行初始化,這樣一個真正可用的對象才算產(chǎn)生出來。

對象內(nèi)存布局

在HotSpot虛擬機(jī)中,對象在內(nèi)存中存儲的布局可以分為3塊區(qū)域:對象頭(Header)、實例數(shù)據(jù)(Instance Data)和對齊填充(Padding)。

對象頭

HotSpot虛擬機(jī)的對象頭包括兩部分信息:運(yùn)行時數(shù)據(jù)和類型指針。

運(yùn)行時數(shù)據(jù)

用于存儲對象自身的運(yùn)行時數(shù)據(jù),如哈希碼(HashCode)、GC分代年齡、鎖狀態(tài)標(biāo)志、線程持有的鎖、偏向線程ID、偏向時間戳等。

對象頭

類型指針

即對象指向它的類元數(shù)據(jù)的指針,虛擬機(jī)通過這個指針來確定這個對象是哪個類的實例。

如果對象是一個Java數(shù)組,那在對象頭中還必須有一塊用于記錄數(shù)組長度的數(shù)據(jù),因為虛擬機(jī)可以通過普通Java對象的元數(shù)據(jù)信息確定Java對象的大小,但是從數(shù)組的元數(shù)據(jù)中無法確定數(shù)組的大小。
(并不是所有的虛擬機(jī)實現(xiàn)都必須在對象數(shù)據(jù)上保留類型指針,換句話說,查找對象的元數(shù)據(jù)并不一定要經(jīng)過對象本身,可參考對象的訪問定位)

實例數(shù)據(jù)

實例數(shù)據(jù)部分是對象真正存儲的有效信息,也是在程序代碼中所定義的各種類型的字段內(nèi)容。無論是從父類中繼承下來的,還是在子類中定義的,都需要記錄下來。HotSpot虛擬機(jī)默認(rèn)的分配策略為longs/doubles、ints、shorts/chars、bytes/booleans、oop,從分配策略中可以看出,相同寬度的字段總是分配到一起。

對齊填充

HotSpot虛擬機(jī)要求對象的起始地址必須是8字節(jié)的整數(shù)倍,也就是對象的大小必須是8字節(jié)的整數(shù)倍。而對象頭部分正好是8字節(jié)的倍數(shù)(1倍或者2倍),因此,當(dāng)對象實例數(shù)據(jù)部分沒有對齊的時候,就需要通過對齊填充來補(bǔ)全。

對象訪問定位

Java程序需要通過棧上的引用數(shù)據(jù)來操作堆上的具體對象。對象的訪問方式取決于虛擬機(jī)實現(xiàn),目前主流的訪問方式有使用句柄和直接指針兩種。

句柄,可以理解為指向指針的指針,維護(hù)指向?qū)ο蟮闹羔樧兓?,而對象的句柄本身不發(fā)生變化;指針,指向?qū)ο?,代表對象的?nèi)存地址。

句柄
Java堆中劃分出一塊內(nèi)存來作為句柄池,引用中存儲對象的句柄地址,而句柄中包含了對象實例數(shù)據(jù)與類型數(shù)據(jù)各自的具體地址信息。

句柄訪問對象

優(yōu)勢:引用中存儲的是穩(wěn)定的句柄地址,在對象被移動(垃圾收集時移動對象是非常普遍的行為)時只會改變句柄中的實例數(shù)據(jù)指針,而引用本身不需要修改。

直接指針

如果使用直接指針訪問,那么Java堆對象的布局中就必須考慮如何放置訪問類型數(shù)據(jù)的相關(guān)信息,而引用中存儲的直接就是對象地址。

直接內(nèi)存訪問對象

優(yōu)勢:速度更快,節(jié)省了一次指針定位的時間開銷。由于對象的訪問在Java中非常頻繁,因此這類開銷積少成多后也是非??捎^的執(zhí)行成本。(例如HotSpot)

參考
1、周志明,深入理解Java虛擬機(jī):JVM高級特性與最佳實踐,機(jī)械工業(yè)出版社

更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java面向?qū)ο蟪绦蛟O(shè)計入門與進(jìn)階教程》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總

希望本文所述對大家java程序設(shè)計有所幫助。

相關(guān)文章

  • Springboot報錯java.lang.NullPointerException: null問題

    Springboot報錯java.lang.NullPointerException: null問題

    這篇文章主要介紹了Springboot報錯java.lang.NullPointerException: null問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • Springboot 使用 maven-resources-plugin 打包變量替換jar沒有打包進(jìn)去、Jar包沒有被使用的解決方法

    Springboot 使用 maven-resources-plugin 打包變量替換ja

    這篇文章主要介紹了Springboot 使用 maven-resources-plugin 打包變量替換jar沒有打包進(jìn)去、Jar包沒有被使用的解決方法,本文給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2024-08-08
  • 關(guān)于Java中Comparable 和 Comparator的用法

    關(guān)于Java中Comparable 和 Comparator的用法

    這篇文章主要介紹了關(guān)于Java中Comparable 和 Comparator的用法,Comparable 和 Comparator 是關(guān)于排序的兩個接口,用來實現(xiàn) Java 集合中的的排序功能,需要的朋友可以參考下
    2023-04-04
  • 詳解Springboot分布式限流實踐

    詳解Springboot分布式限流實踐

    這篇文章主要介紹了詳解Springboot分布式限流實踐 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-06-06
  • 淺談spring-boot 允許接口跨域并實現(xiàn)攔截(CORS)

    淺談spring-boot 允許接口跨域并實現(xiàn)攔截(CORS)

    本篇文章主要介紹了淺談spring-boot 允許接口跨域并實現(xiàn)攔截(CORS),具有一定的參考價值,有興趣的可以了解一下
    2017-08-08
  • Spring Boot異步輸出Logback日志方法詳解

    Spring Boot異步輸出Logback日志方法詳解

    這篇文章主要給大家介紹了關(guān)于Spring Boot異步輸出Logback日志的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Java讓多線程按順序執(zhí)行的幾種方法

    Java讓多線程按順序執(zhí)行的幾種方法

    本文主要介紹了Java讓多線程按順序執(zhí)行的幾種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Java給PDF加水印并合并多個文件

    Java給PDF加水印并合并多個文件

    大家好,本篇文章主要講的是Java給PDF加水印并合并多個文件,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-02-02
  • 初步學(xué)習(xí)Java中線程的實現(xiàn)與生命周期

    初步學(xué)習(xí)Java中線程的實現(xiàn)與生命周期

    這篇文章主要介紹了初步學(xué)習(xí)Java中線程的實現(xiàn)與生命周期,線程方面的知識是Java學(xué)習(xí)過程中的重點和難點,需要的朋友可以參考下
    2015-11-11
  • Spring Bean配置方式總結(jié)

    Spring Bean配置方式總結(jié)

    定義Spring Bcan的3種方式分別是:基于XML 的方式配置、基于注解掃播方式配置、基于元數(shù)據(jù)類的配置,本文就通過代碼示例給大家詳細(xì)講講這三種配置方式,需要的朋友可以參考下
    2023-12-12

最新評論

泸西县| 奉化市| 县级市| 澄江县| 四会市| 辽宁省| 盐城市| 丘北县| 丰台区| 江达县| 闽侯县| 会同县| 长寿区| 揭东县| 阳泉市| 卢湾区| 东乌珠穆沁旗| 沛县| 嘉善县| 宁国市| 平湖市| 板桥市| 陇南市| 德昌县| 北海市| 武鸣县| 陇西县| 罗甸县| 怀化市| 尉犁县| 天门市| 开江县| 土默特左旗| 云安县| 丹凤县| 胶州市| 北京市| 克什克腾旗| 永登县| 交口县| 华安县|