衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

淺析JVM之對(duì)象創(chuàng)建流程及對(duì)象內(nèi)存布局

jf_78858299 ? 來(lái)源:北洋洋洋 ? 作者:北洋 ? 2023-02-02 11:16 ? 次閱讀

對(duì)象創(chuàng)建流程

當(dāng)JAVA虛擬機(jī)碰到new字節(jié)碼指令時(shí),首先會(huì)去常量池中查找是否有對(duì)應(yīng)的類(lèi)名(也就是去查找是否有對(duì)應(yīng)的符號(hào)引用),然后去檢查這個(gè)符號(hào)引用代表的類(lèi)是否已經(jīng)被加載,解析和初始化過(guò)。如果沒(méi)有會(huì)先進(jìn)行類(lèi)加載過(guò)程。

當(dāng)類(lèi)加載后,虛擬機(jī)將會(huì)為其分配內(nèi)存,為其分配的內(nèi)存大小是可知的,下面的內(nèi)存布局將會(huì)講解為什么是可知的。

分配內(nèi)存

分配內(nèi)存這時(shí)候有兩種情況:

1.假如堆里面的內(nèi)存是整齊的,用過(guò)的在一邊,沒(méi)有用過(guò)的內(nèi)存放在另外一邊(后期配圖),這個(gè)時(shí)候中間有個(gè)指針來(lái)作為兩邊內(nèi)存的界限,當(dāng)內(nèi)存分配時(shí),指針移動(dòng)對(duì)象內(nèi)存大小對(duì)應(yīng)的距離即可,這種叫==指針碰撞==。

2.堆里面的內(nèi)存空間不是規(guī)整的,這就需要記錄下來(lái)哪些內(nèi)存是可用的,哪些內(nèi)存是已經(jīng)被占用了的。這種方式就叫做==空閑列表==:將內(nèi)存中空閑內(nèi)存塊記錄到列表里面。當(dāng)分配對(duì)象時(shí),直接從空閑列表里面進(jìn)行取出對(duì)應(yīng)大小的內(nèi)存塊即可。

這兩種情況又是根據(jù)采用的垃圾收集器是否帶有==空間壓縮整理的能力==劃分,如果垃圾收集器已經(jīng)具備了空間壓縮整理的能力那么他的內(nèi)存空間就是==被整理好的==,直接使用==指針碰撞==就好;但是如果是基于清除算法決定的垃圾回收器時(shí),就只能用復(fù)雜的空閑列表來(lái)分配內(nèi)存。

并發(fā)解決方法

但是如果發(fā)生并發(fā)的話,可能在分配一個(gè)對(duì)象空間的時(shí)候又碰到另外一個(gè)線程也在分配空間,這個(gè)時(shí)候就會(huì)出現(xiàn)問(wèn)題,解決方式有兩種:

1.通過(guò)CAS進(jìn)行同步處理,基于失敗重試的原則;2.將堆里面的空間進(jìn)行按線程分配,每個(gè)線程在隊(duì)中都會(huì)有塊內(nèi)存,當(dāng)線程分配內(nèi)存時(shí),直接分配到自己線程的那塊內(nèi)存當(dāng)中,當(dāng)那小塊內(nèi)存用完時(shí),在進(jìn)行CAS同步申請(qǐng)新的內(nèi)存,這種小塊內(nèi)存叫做==本地線程分配緩存(TLAB)==。

設(shè)置初始值

==分配完內(nèi)存之后需要給這部分內(nèi)存設(shè)置零值,不包括對(duì)象頭。當(dāng)通過(guò)TLAB分配內(nèi)存時(shí),其實(shí)在分配內(nèi)存的時(shí)候就可以設(shè)置零值,不需要等到分配完在設(shè)置,因?yàn)檫@部分內(nèi)存區(qū)域是已知的不會(huì)出現(xiàn)分配時(shí)產(chǎn)生并發(fā)的問(wèn)題==

在程序中可能會(huì)出現(xiàn)的問(wèn)題

解釋?zhuān)哼@步操作也就是說(shuō)當(dāng)對(duì)象分配到內(nèi)存后就可以直接使用里面的字段,==但是這個(gè)是初始值==,如果說(shuō)當(dāng)我分配完內(nèi)存后直接使用這個(gè)字段的話程序肯定會(huì)出問(wèn)題(因?yàn)?a href="http://www.zgszdi.cn/v/tag/132/" target="_blank">CPU是亂序執(zhí)行的,當(dāng)兩個(gè)操作互不關(guān)聯(lián)時(shí),一個(gè)操作耗時(shí)一個(gè)操作不耗時(shí),這時(shí)候CPU會(huì)進(jìn)行優(yōu)化讓不耗時(shí)的先運(yùn)行。而且一個(gè)創(chuàng)建對(duì)象的過(guò)程需要多行字節(jié)碼來(lái)完成,所以可能會(huì)出現(xiàn)重排序的問(wèn)題,但是這個(gè)概率特別低)這時(shí)候就需要用volatile關(guān)鍵字來(lái)保證有序性。

?其本身是通過(guò)在JVM平臺(tái)上面的Load,Store兩個(gè)讀寫(xiě)屏障組合來(lái)保證的,對(duì)應(yīng)于intel的X86來(lái)說(shuō)是基于MESI協(xié)議來(lái)保證的。其實(shí)JVM平臺(tái)規(guī)定了一些不能亂序執(zhí)行的原則:HappenBefore原則,里面就規(guī)定了volitaile關(guān)鍵字

?

設(shè)置對(duì)象頭

當(dāng)對(duì)象中的字段設(shè)置為對(duì)應(yīng)的默認(rèn)值(零值)時(shí),需要設(shè)置對(duì)象頭里面的數(shù)據(jù),這部分?jǐn)?shù)據(jù)包括兩部分:

對(duì)象頭數(shù)據(jù)結(jié)構(gòu)

1.==對(duì)象自身運(yùn)行時(shí)的數(shù)據(jù)== 比如:哈希碼(延遲到真正調(diào)用hashcode()方法時(shí)才生成) 鎖狀態(tài)標(biāo)志 線程持有鎖 偏向鎖的線程ID 偏向時(shí)間戳 對(duì)象分代年齡 ...... 在未開(kāi)啟壓縮指針的情況下,根據(jù)32位虛擬機(jī)和64位虛擬機(jī)不同,這部分?jǐn)?shù)據(jù)的總大小分別是32個(gè)比特和64個(gè)比特。這部分?jǐn)?shù)據(jù)叫做“Mark Word”,由于對(duì)象運(yùn)行時(shí)存儲(chǔ)的數(shù)據(jù)很多,所以Mark Word是一個(gè)動(dòng)態(tài)的數(shù)據(jù)結(jié)構(gòu),有些數(shù)據(jù)其實(shí)根本用不到所以某些數(shù)據(jù)其實(shí)是沒(méi)有必要立馬就存儲(chǔ)的。

?32位的虛擬機(jī)中,MarkWord是32個(gè)比特,其中哈希碼占用25個(gè)比特,分代年齡占用4個(gè),鎖標(biāo)志位占用兩個(gè),剩下的另外一個(gè)比特固定為0。

?

2.==類(lèi)型指針== 指向類(lèi)的元數(shù)據(jù)信息,通過(guò)這個(gè)指針來(lái)確定該對(duì)象屬于哪個(gè)類(lèi)的實(shí)例。

?(不是所有的虛擬機(jī)都必須在對(duì)象數(shù)據(jù)上設(shè)置類(lèi)型指針)

?

==當(dāng)對(duì)象是數(shù)組。。。。==

?如果對(duì)象是數(shù)組,在對(duì)象頭中還會(huì)記錄數(shù)組長(zhǎng)度,普通JAVA對(duì)象可以通過(guò)找到類(lèi)的元數(shù)據(jù)信息確定JAVA對(duì)象的大小,但是數(shù)組長(zhǎng)度是不能通過(guò)類(lèi)的元數(shù)據(jù)信息推導(dǎo)出來(lái)的,所以需要在對(duì)象頭中設(shè)置數(shù)組長(zhǎng)度

?

Class文件的<.init>

當(dāng)設(shè)置完字段的默認(rèn)值和對(duì)象頭的數(shù)據(jù)后,這個(gè)時(shí)候該調(diào)用Class對(duì)象的<.init>方法了即構(gòu)造函數(shù)。

對(duì)象的內(nèi)存布局

當(dāng)了解完前面的對(duì)象創(chuàng)建流程時(shí),相信對(duì)于對(duì)象在堆中的內(nèi)存布局也已經(jīng)有兩大概的輪廓了,接下來(lái)進(jìn)行總結(jié):

==分為三部分:對(duì)象頭,實(shí)例數(shù)據(jù),對(duì)齊填充==

1.對(duì)象頭前面已經(jīng)詳細(xì)講過(guò)了,就不在闡述了

2.實(shí)例數(shù)據(jù):記錄父類(lèi)和當(dāng)前類(lèi)中定義的字段,存儲(chǔ)的順序默認(rèn)是:long/doubles , ints , shorts/chars , bytes/booleans , oops。默認(rèn)順序遵從的原則是相同寬度的字段分配到一起,接著父類(lèi)定義的變量在子類(lèi)定義的變量的簽名。

3.對(duì)齊填充:==不是必然的== 占位符。由于HotSpot虛擬機(jī)自動(dòng)內(nèi)存管理系統(tǒng)要求對(duì)象的起始地址必須是8字節(jié)的整數(shù)倍,也就是對(duì)象的大小都必須是8的倍數(shù)。對(duì)象頭剛剛說(shuō)了無(wú)非是32比特或者64比特默認(rèn)就是八字節(jié)的,所以當(dāng)實(shí)例數(shù)據(jù)滿足八的倍數(shù)時(shí),就不需要占位符,這部分?jǐn)?shù)據(jù)也就沒(méi)有;如果不滿足八的倍數(shù),將添加占位符使整個(gè)對(duì)象大小為八的倍數(shù)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2975

    瀏覽量

    105147
  • JVM
    JVM
    +關(guān)注

    關(guān)注

    0

    文章

    158

    瀏覽量

    12260
  • 虛擬機(jī)
    +關(guān)注

    關(guān)注

    1

    文章

    940

    瀏覽量

    28427
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    請(qǐng)問(wèn)單例對(duì)象會(huì)被jvm的gc時(shí)回收嗎?

    單例對(duì)象會(huì)被jvm的gc時(shí)回收嗎?
    發(fā)表于 11-09 07:02

    解讀rtt的c的面向對(duì)象對(duì)象創(chuàng)建及其啟動(dòng)初始化流程

    解讀rtt的c的面向對(duì)象對(duì)象創(chuàng)建及其啟動(dòng)初始化流程,最后總結(jié)面向對(duì)象語(yǔ)言與c面向對(duì)象的區(qū)別。目
    發(fā)表于 07-05 11:01

    java如何創(chuàng)建對(duì)象的分析

    作為Java開(kāi)發(fā)者,我們每天創(chuàng)建很多對(duì)象,但我們通常使用依賴(lài)管理系統(tǒng),比如Spring去創(chuàng)建對(duì)象。然而這里有很多創(chuàng)建
    發(fā)表于 09-27 14:36 ?0次下載

    使用JavaScript創(chuàng)建對(duì)象的方法和案例

    Javascript中的一切幾乎都是對(duì)象,無(wú)論是數(shù)組還是函數(shù)。本文將教你使用JavaScript創(chuàng)建對(duì)象的三種方法。
    的頭像 發(fā)表于 07-06 09:41 ?2969次閱讀

    一文詳解Java對(duì)象內(nèi)存布局

    這個(gè)實(shí)例對(duì)象是以怎樣的形態(tài)存在內(nèi)存中的? 一個(gè)Object對(duì)象內(nèi)存中占用多大? 對(duì)象中的屬性是如何在內(nèi)
    發(fā)表于 09-30 14:38 ?1225次閱讀
    一文詳解Java<b class='flag-5'>對(duì)象</b>的<b class='flag-5'>內(nèi)存</b><b class='flag-5'>布局</b>

    JVM內(nèi)存布局的多方面了解

      JVM內(nèi)存布局規(guī)定了Java在運(yùn)行過(guò)程中內(nèi)存申請(qǐng)、分配、管理的策略,保證了JVM的穩(wěn)定高效運(yùn)行。不同的
    發(fā)表于 07-08 15:09 ?428次閱讀

    在JavaScript中動(dòng)態(tài)的創(chuàng)建QML對(duì)象

    在實(shí)際QML應(yīng)用開(kāi)發(fā)中,我們可以在JavaScript中動(dòng)態(tài)的創(chuàng)建QML對(duì)象。這樣做可以延遲對(duì)象的實(shí)例化,當(dāng)我們?cè)谛枰?b class='flag-5'>創(chuàng)建對(duì)象的時(shí)候才在Ja
    的頭像 發(fā)表于 09-01 10:42 ?1620次閱讀

    探討JVM內(nèi)存布局

    JVM內(nèi)存布局規(guī)定了Java在運(yùn)行過(guò)程中內(nèi)存申請(qǐng)、分配、管理的策略,保證了JVM的穩(wěn)定高效運(yùn)行。
    的頭像 發(fā)表于 09-09 15:57 ?877次閱讀

    Java中創(chuàng)建對(duì)象有哪些方式

    1 問(wèn)題 作為Java開(kāi)發(fā)者,經(jīng)常創(chuàng)建很多對(duì)象,你是否知道Java中創(chuàng)建對(duì)象有哪些方式呢?
    的頭像 發(fā)表于 02-24 10:29 ?1088次閱讀

    JVM內(nèi)存布局詳解

    JVM內(nèi)存布局規(guī)定了Java在運(yùn)行過(guò)程中內(nèi)存申請(qǐng)、分配、管理的策略,保證了JVM的穩(wěn)定高效運(yùn)行。不同的J
    的頭像 發(fā)表于 04-26 10:10 ?569次閱讀
    <b class='flag-5'>JVM</b><b class='flag-5'>內(nèi)存</b><b class='flag-5'>布局</b>詳解

    Java反射技術(shù)實(shí)現(xiàn)對(duì)象創(chuàng)建

    一. 基礎(chǔ)概念 Java中,一般我們創(chuàng)建一個(gè)對(duì)象可能會(huì)選擇new一下個(gè)實(shí)例。但是隨著我們技術(shù)的不斷提升,我們也學(xué)習(xí)到了,可以通過(guò)反射技術(shù)實(shí)現(xiàn)對(duì)象創(chuàng)建。 可是,你有沒(méi)有想一下,什么時(shí)候
    的頭像 發(fā)表于 05-22 14:25 ?2359次閱讀
    Java反射技術(shù)實(shí)現(xiàn)<b class='flag-5'>對(duì)象</b>的<b class='flag-5'>創(chuàng)建</b>

    詳解Java虛擬機(jī)的JVM內(nèi)存布局

    JVM內(nèi)存布局規(guī)定了Java在運(yùn)行過(guò)程中內(nèi)存申請(qǐng)、分配、管理的策略,保證了JVM的穩(wěn)定高效運(yùn)行。不同的J
    的頭像 發(fā)表于 07-13 09:52 ?555次閱讀
    詳解Java虛擬機(jī)的<b class='flag-5'>JVM</b><b class='flag-5'>內(nèi)存</b><b class='flag-5'>布局</b>

    JVM內(nèi)存對(duì)象監(jiān)控和優(yōu)化問(wèn)題描述及解決辦法

    服務(wù)器內(nèi)存問(wèn)題是影響應(yīng)用程序性能和穩(wěn)定性的重要因素之一,需要及時(shí)排查和優(yōu)化。本文介紹了某核心服務(wù)內(nèi)存問(wèn)題排查與解決過(guò)程。首先在JVM與大對(duì)象優(yōu)化上進(jìn)行了有效的實(shí)踐,其次在故障轉(zhuǎn)移與大
    的頭像 發(fā)表于 08-28 11:39 ?1205次閱讀
    <b class='flag-5'>JVM</b><b class='flag-5'>內(nèi)存</b>大<b class='flag-5'>對(duì)象</b>監(jiān)控和優(yōu)化問(wèn)題描述及解決辦法

    淺析JVM內(nèi)存對(duì)象監(jiān)控和優(yōu)化實(shí)踐的過(guò)程

    音樂(lè)業(yè)務(wù)中,core服務(wù)主要提供歌曲、歌手等元數(shù)據(jù)與用戶(hù)資產(chǎn)查詢(xún)。隨著元數(shù)據(jù)與用戶(hù)資產(chǎn)查詢(xún)量的增長(zhǎng),一些JVM內(nèi)存問(wèn)題也逐漸顯露,例如GC頻繁、耗時(shí)長(zhǎng),在高峰期RPC調(diào)用超時(shí)等問(wèn)題,導(dǎo)致業(yè)務(wù)核心功能受損。
    的頭像 發(fā)表于 09-06 10:14 ?647次閱讀
    <b class='flag-5'>淺析</b><b class='flag-5'>JVM</b><b class='flag-5'>內(nèi)存</b>大<b class='flag-5'>對(duì)象</b>監(jiān)控和優(yōu)化實(shí)踐的過(guò)程

    jvm內(nèi)存區(qū)域由哪幾部分組成

    。下面將詳細(xì)介紹這些部分。 堆內(nèi)存(Heap Memory):堆內(nèi)存JVM中最大的一塊內(nèi)存區(qū)域,用來(lái)存儲(chǔ)對(duì)象實(shí)例和數(shù)組
    的頭像 發(fā)表于 12-05 14:10 ?868次閱讀
    百家乐五湖四海娱乐| 八大胜百家乐的玩法技巧和规则| 百家乐开发公司| 百家乐官网娱乐分析软件v4.0| 百家乐官网太阳城开户| 棋牌中心| 大发888娱乐城游戏lm0| 百家乐23珠路打法| 百家乐街机| 网上百家乐正规代理| 斗首24山择日天机择日| 罗浮宫百家乐官网的玩法技巧和规则 | 七胜百家乐官网娱乐场| 百家乐官网现金网信誉排名| 百家乐官网和抽水官网| 大发888娱乐场zb8| 大发888百科| 大发888娱乐城注册lm0| 全讯网址| 大发888技巧| 大发888娱乐城安装| 大发888娱乐城客户端迅雷下载| 幸运水果机游戏下载| 百家乐盛大娱乐城城| 百家乐烫金筹码| 太阳城百家乐怎么出千| 百家乐电话投注多少| 百家乐分析网| 百家乐娱乐网真人娱乐网| 星级百家乐技巧| 百家乐最新首存优惠| 百家乐揽子打法| 玩百家乐是否有技巧| 澳门百家乐有没有假| 百家乐桌手机套| 百家乐真人游戏娱乐| 百家乐大娱乐场开户注册| 名仕百家乐的玩法技巧和规则| 康莱德百家乐的玩法技巧和规则 | 立博百家乐官网的玩法技巧和规则| 玩百家乐官网怎么能赢呢|