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

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

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

JVM入門之關(guān)于GC的擴(kuò)展知識(shí)2

jf_78858299 ? 來源:北洋洋洋 ? 作者:北洋 ? 2023-02-10 11:35 ? 次閱讀

5.一個(gè)"小Bug":線程如果不執(zhí)行呢?

上面說到過現(xiàn)在虛擬機(jī)采用的幾乎都是主動(dòng)式中斷來中斷線程,而其實(shí)現(xiàn)又是通過 「線程執(zhí)行過程中不斷輪詢標(biāo)志位」 產(chǎn)生自陷異常信號(hào)在異常處理表中進(jìn)行中斷線程,

大家有沒有發(fā)現(xiàn)有個(gè)小bug:如果我輪詢的操作一直得不到執(zhí)行呢?這個(gè)時(shí)候我又該如何讓虛擬機(jī)進(jìn)入垃圾回收狀態(tài)。

其實(shí)不一定都需要進(jìn)行中斷線程來保證,回想下STW是為什么:因?yàn)槿绻@個(gè)時(shí)候用戶線程還在執(zhí)行的話內(nèi)存中的引用關(guān)系可能會(huì)發(fā)生變化,所以才需要進(jìn)行STW。如果一個(gè)線程沒有得到CPU時(shí)間片執(zhí)行(java中的線程對(duì)應(yīng)于操作系統(tǒng)的線程,對(duì)應(yīng)關(guān)系也可以找筆者之前的關(guān)于SignCatcher對(duì)線程的理解進(jìn)行查閱),但是我可以確保其中一部分代碼區(qū)域是不會(huì)改變內(nèi)存引用關(guān)系的,這樣也可以不用管這些線程。

引入Safe Region(安全區(qū)域)解決

?

“安全區(qū)域:這部分代碼不會(huì)使內(nèi)存中的引用關(guān)系發(fā)生變化”,因此只要進(jìn)入了安全區(qū)域,虛擬機(jī)就不會(huì)管這些線程。當(dāng)線程離開安全區(qū)域后,如果這個(gè)時(shí)候引用鏈還沒有形成(也就是通過GC Roots遍歷堆內(nèi)存)那么是不能離開的,一直等待直至引用鏈形成(或者完成了垃圾回收器需要暫停用戶線程的階段)收到信號(hào)為止。

?

6. GC Roots會(huì)隨著運(yùn)行時(shí)間變長(zhǎng)而增加嗎?

基礎(chǔ)知識(shí)介紹

根據(jù)堆中的不同區(qū)域(分代設(shè)計(jì))和回收內(nèi)存空間來判定分為不同的GC名稱:局部回收:Minor GC,MajorGC,..... 整個(gè)內(nèi)存回收:Full GC

如果存在“跨代引用”(最典型的比如老年代對(duì)象引用年輕代對(duì)象),比如發(fā)生Minor GC時(shí),只遍歷普通的GC Roots對(duì)象其實(shí)結(jié)果并不準(zhǔn)確( 「某些對(duì)象雖然本身不屬于GC Roots但是隨著經(jīng)歷的GC次數(shù)變多成為老年代對(duì)象」 ),如果這個(gè)時(shí)候?qū)⑦@個(gè)引用的年輕代對(duì)象標(biāo)記為垃圾清除后,老年代中的對(duì)象就會(huì)有問題,所以引用鏈形成的過程中還需要 「遍歷整個(gè)老年代來保證結(jié)果準(zhǔn)確」 。

CPU的緩存行技術(shù)及偽共享解決方案

!

記憶集

跨域可以理解為跨內(nèi)存訪問或者訪問其他分代里面的內(nèi)存

上面遍歷整個(gè)老年代這個(gè)過程聽起來就很耗時(shí)哈哈,事實(shí)也確實(shí)如此。那么我們可以引入這么一個(gè)概念:如果你引用了其他內(nèi)存里面的對(duì)象那么我把你存放到其他內(nèi)存里面的一個(gè)數(shù)據(jù)結(jié)構(gòu)里面,之后其他內(nèi)存回收的時(shí)候只需要把之前添加到數(shù)據(jù)結(jié)構(gòu)里面的對(duì)象加入到GC Roots中即可。

我們優(yōu)化一下: 「每個(gè)不同的分代中都存著一個(gè)數(shù)組」 ,這個(gè)數(shù)組中對(duì)堆內(nèi)存進(jìn)行一個(gè)映射, 我數(shù)組中的每一小塊對(duì)應(yīng)的元素是分代中固定大小的內(nèi)存(比如我第一個(gè)數(shù)組下標(biāo)表示我引用的是0到100,第二個(gè)數(shù)組下標(biāo)表示引用的是100-200以此類推)。 「當(dāng)我第一個(gè)數(shù)組下標(biāo)對(duì)應(yīng)內(nèi)存跨域引用了其他分代中的內(nèi)存,我將把第一個(gè)數(shù)組下標(biāo)對(duì)應(yīng)的內(nèi)存的元素值標(biāo)識(shí)為1代表臟(Dirty)」 ,沒有則為0。當(dāng)垃圾回收時(shí),我就知道哪部分內(nèi)存是跨代引用并將他們加入到GC Roots進(jìn)行掃描(將數(shù)組中元素為1對(duì)應(yīng)的內(nèi)存對(duì)象加入GC Roots中)。

根據(jù)我映射的內(nèi)存大小精度又可以進(jìn)行細(xì)分:1.字長(zhǎng)精度:只記錄一個(gè)機(jī)器字長(zhǎng)(處理器的尋址位數(shù))該字包含跨代指針

2.對(duì)象精度:記錄一個(gè)對(duì)象(對(duì)象字段中含有跨代指針)

3.卡精度:記錄一塊內(nèi)存區(qū)域(該區(qū)域有對(duì)象包含跨代指針)

最常用的精度

采用“卡精度”的記憶集是通過“卡表”這個(gè)數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn)的。

使用精度為卡,這個(gè)記憶集的實(shí)現(xiàn)方式也被稱為 「卡表」 ,卡表中其實(shí)是字節(jié)數(shù)組結(jié)構(gòu),每個(gè)數(shù)組中的元素都對(duì)應(yīng)一部分指定大小內(nèi)存塊,這部分內(nèi)存被稱作 「卡頁(yè)」 ,當(dāng)卡頁(yè)中的內(nèi)存塊中引用了其他的內(nèi)存塊中的一個(gè)或多個(gè)對(duì)象,就會(huì)將卡頁(yè)中的元素值變?yōu)橐弧W優(yōu)橐坏木褪桥K數(shù)據(jù),收集時(shí)講這部分內(nèi)存加入到gc roots中。也就是這樣的:

可能出現(xiàn)的問題

一, 「何時(shí)進(jìn)行更新卡表?」 先看我這張圖哈哈,字不好看,但是大致意思是差不多的。

?

我在寫后屏障中進(jìn)行更新卡表就可以保證我的卡表記錄是正確的。

?

二, 「“偽共享引起的問題”」 上面剛剛講過CPU的緩存行技術(shù),簡(jiǎn)單來說就是如果兩個(gè)線程中兩個(gè)獨(dú)立的變量在同一塊緩存行中,那么不管是哪個(gè)線程修改,另外一個(gè)線程都需要重新從主存中讀取,而設(shè)置緩存行就是為了加快讀取效率,所以這樣勢(shì)必會(huì)降低效率。

想想剛剛我們記憶集處理方式,如果卡頁(yè)對(duì)應(yīng)的內(nèi)存中發(fā)生跨代引用,那么就會(huì)對(duì)卡表進(jìn)行更新;上面說的“偽共享”也會(huì)在這里出現(xiàn)而且影響性能,比如: 「一個(gè)緩存行六十四個(gè)字節(jié);一個(gè)卡表中的一個(gè)元素是一個(gè)字節(jié),每個(gè)元素對(duì)應(yīng)的一個(gè)卡頁(yè)存儲(chǔ)的是512字節(jié),也就是一個(gè)卡表中64個(gè)元素在一個(gè)緩存行,而這64個(gè)元素對(duì)應(yīng)的總卡頁(yè)內(nèi)存為32KB(64 X 512字節(jié))」 ,如果兩個(gè)線程中的變量分配到了這部分內(nèi)存中,之后變量發(fā)生跨代引用更新卡表元素時(shí)就會(huì)導(dǎo)致另一個(gè)線程的緩存行失效而從主存中去拿。所以應(yīng)該減少更新卡表這個(gè)操作,如果已經(jīng)更新過臟數(shù)據(jù)了就不需要進(jìn)行更新卡表了。

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

    關(guān)注

    88

    文章

    3521

    瀏覽量

    93275
  • GC
    GC
    +關(guān)注

    關(guān)注

    0

    文章

    9

    瀏覽量

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

    關(guān)注

    0

    文章

    155

    瀏覽量

    12168
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    電子技術(shù)入門維修基礎(chǔ)知識(shí)

    電子技術(shù)入門維修基礎(chǔ)知識(shí)
    發(fā)表于 08-17 20:03

    請(qǐng)問單例對(duì)象會(huì)被jvmgc時(shí)回收嗎?

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

    JVM知識(shí)點(diǎn)匯總,不看肯定后悔

    JVM知識(shí)點(diǎn)匯總,不看肯定后悔
    發(fā)表于 11-30 06:13

    看看基于JDK中自帶JVM工具的用法

    查詢很多參數(shù)的默認(rèn)值;該命令還可以在運(yùn)行時(shí)動(dòng)態(tài)調(diào)整部分參數(shù),只是很少被使用;3、jstat命令jstat :以指定的頻率輸出JVM的監(jiān)控指標(biāo),下述命令輸出內(nèi)存占用和GC相關(guān)信息,每隔3秒輸出一次,連續(xù)
    發(fā)表于 11-16 15:30

    初學(xué)者AVR軟件入門基礎(chǔ)知識(shí)2

    初學(xué)者AVR軟件入門基礎(chǔ)知識(shí)2
    的頭像 發(fā)表于 07-04 09:50 ?2557次閱讀

    Java:JVM虛擬機(jī)的入門知識(shí)

    Java開發(fā)現(xiàn)在面試越來越難了,進(jìn)大廠必備的JVM、多線程高并發(fā)這都是最基礎(chǔ)的知識(shí)了,今天我們一起來學(xué)習(xí)Java虛擬機(jī)入門。
    的頭像 發(fā)表于 07-01 11:43 ?2229次閱讀
    Java:<b class='flag-5'>JVM</b>虛擬機(jī)的<b class='flag-5'>入門</b><b class='flag-5'>知識(shí)</b>

    如何解決JVM解釋器導(dǎo)致應(yīng)用崩潰的bug

    bug 導(dǎo)致在弱內(nèi)存模型的平臺(tái)上 Crash。 在分析過程中,涉及到非常多的 JVM 內(nèi)部知識(shí),比如對(duì)象頭、GC 復(fù)制算法操作、CAS 操作、字節(jié)碼執(zhí)行、內(nèi)存序等,希望對(duì)讀者有所幫助。本文介紹了一般分析
    的頭像 發(fā)表于 08-27 09:58 ?2256次閱讀
    如何解決<b class='flag-5'>JVM</b>解釋器導(dǎo)致應(yīng)用崩潰的bug

    關(guān)于JVM的調(diào)優(yōu)知識(shí)

    最近很多小伙伴跟我說,自己學(xué)了不少JVM的調(diào)優(yōu)知識(shí),但是在實(shí)際工作中卻不知道何時(shí)對(duì)JVM進(jìn)行調(diào)優(yōu)。今天,我就為大家介紹幾種JVM調(diào)優(yōu)的場(chǎng)景。
    的頭像 發(fā)表于 09-14 14:54 ?718次閱讀

    一次JVM GC長(zhǎng)暫停的排查過程

    在高并發(fā)下,Java 程序的 GC 問題屬于很典型的一類問題,帶來的影響往往會(huì)被進(jìn)一步放大。不管是「GC 頻率過快」還是「GC 耗時(shí)太長(zhǎng)」,由于 GC 期間都存在 Stop The W
    的頭像 發(fā)表于 01-17 10:08 ?515次閱讀

    JVM入門歷代垃圾回收器 2

    很多人經(jīng)常把這兩個(gè)搞混,當(dāng)然筆者剛開始的時(shí)候也是傻傻分不清楚。其實(shí)只要記住并行說的是GC 線程之間的關(guān)系,而并發(fā)說的是GC和用戶線程之間的關(guān)系
    的頭像 發(fā)表于 02-10 11:29 ?482次閱讀
    <b class='flag-5'>JVM</b><b class='flag-5'>入門</b><b class='flag-5'>之</b>歷代垃圾回收器 <b class='flag-5'>2</b>

    JVM入門關(guān)于GC擴(kuò)展知識(shí)1

    本章主要是對(duì)上一篇文章講的垃圾回收機(jī)制的擴(kuò)展,垃圾回收其實(shí)本身是有很多可以優(yōu)化的點(diǎn)的,本章就進(jìn)行對(duì)這些優(yōu)化點(diǎn)進(jìn)行介紹。
    的頭像 發(fā)表于 02-10 11:35 ?501次閱讀
    <b class='flag-5'>JVM</b><b class='flag-5'>入門</b><b class='flag-5'>之</b><b class='flag-5'>關(guān)于</b><b class='flag-5'>GC</b>的<b class='flag-5'>擴(kuò)展</b><b class='flag-5'>知識(shí)</b>1

    JVM入門垃圾回收算法

    根據(jù)如何判定對(duì)象是垃圾,垃圾回收算法分為兩類:1、 「引用計(jì)數(shù)式垃圾收集」 (判定垃圾是通過引用計(jì)數(shù)器)別名:直接垃圾收集 2、 「追蹤式垃圾收集」 (判定垃圾是通過GC Roots)別名:間接垃圾收集
    的頭像 發(fā)表于 02-10 11:40 ?689次閱讀
    <b class='flag-5'>JVM</b><b class='flag-5'>入門</b><b class='flag-5'>之</b>垃圾回收算法

    JVM的一些重要參數(shù)

    ,默認(rèn)GC 是G1 GC算法。Java 17 默認(rèn)也是G1 GC,其中個(gè)別版本會(huì)有點(diǎn)差異。 下面是常用GC算法使用命令。 GC Algor
    的頭像 發(fā)表于 09-25 15:56 ?388次閱讀

    JVM知識(shí)體系剖析

    從源碼到運(yùn)行、類加載,再到內(nèi)存分配和垃圾回收,以及JVM調(diào)優(yōu)的技巧與實(shí)戰(zhàn)。 理論-實(shí)戰(zhàn)-面試三結(jié)合,帶大家剖析整個(gè)JVM知識(shí)體系,一站解決JVM問題。 1、Oracle Java SE
    的頭像 發(fā)表于 10-10 11:37 ?364次閱讀
    <b class='flag-5'>JVM</b><b class='flag-5'>知識(shí)</b>體系剖析

    從原理聊JVM(一):染色標(biāo)記和垃圾回收算法

    更好地優(yōu)化自己的代碼,并解決一些潛在的性能問題。 本文及后續(xù)文章將從原理聊起,對(duì)JVM的內(nèi)存分配、GC、編譯等知識(shí)進(jìn)行分析和總結(jié)。 1 JVM運(yùn)行時(shí)內(nèi)存劃分 1.1 運(yùn)行時(shí)數(shù)據(jù)區(qū)域 ?
    的頭像 發(fā)表于 08-20 15:25 ?90次閱讀
    從原理聊<b class='flag-5'>JVM</b>(一):染色標(biāo)記和垃圾回收算法