真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

JVM內(nèi)存分區(qū)及GC知識點是什么

JVM內(nèi)存分區(qū)及GC知識點是什么,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、微信小程序開發(fā)、集團企業(yè)網(wǎng)站建設(shè)等服務(wù)項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了張家界免費建站歡迎大家使用!

Java 內(nèi)存分區(qū)

  1. 本地方法棧:native方法調(diào)用時的方法調(diào)用棧,存儲本地棧幀

  2. 虛擬機方法棧:Java的棧,每個線程有一個線程調(diào)用棧,棧的元素是棧幀。棧幀包括:局部變量表、操作數(shù)棧、指向堆中對象的引用、返回地址、附加信息。每個方法調(diào)用時,回向當(dāng)前指向的線程棧頂部壓入一個棧幀,棧幀的大小是固定的,虛擬機通過解析.class文件可以得知。

  3. 堆:堆是所有Java線程共享的一個內(nèi)存區(qū)域,用于分配對象。

  4. 方法區(qū):存儲類的信息(類名、方法信息、字段信息)、靜態(tài)變量、常量池。

  5. 程序計數(shù)器:用于記錄下一條要執(zhí)行的指令,每個線程都有自己的程序計數(shù)器,配合線程棧用于在線程調(diào)度時的線程上下文切換。執(zhí)行本地方法時程序計數(shù)器中沒有值或為undefined。

HotSpot堆內(nèi)存

1.8之前,在HotSpot中堆內(nèi)存分為新生代、老年代、永久代。永久代就是方法區(qū)的實現(xiàn),占用一部分堆內(nèi)存,但永久代不參與垃圾回收。 1.8及置換,HotSpot將堆內(nèi)存分為新生代、老年代。用元數(shù)據(jù)區(qū)實現(xiàn)方法區(qū),且元數(shù)據(jù)區(qū)占用堆外內(nèi)存。

常見的GC算法

  1. 引用計數(shù):每個對象引用被持有時,引用計數(shù)+1。引用賦值為null或銷毀時引用計數(shù)-1。引用計數(shù)為0說明沒有再被使用,可以回收。無法解決循環(huán)引用問題。

  2. 標記-清除算法:第一個階段標記,將存活的對象標記出來;第二個階段是清除,將死亡對象占用的內(nèi)存回收利用。

  3. 標記-整理算法:第一個節(jié)點標記,標記處存貨的對象;第二個階段整理,將存活的對象整理放到另一處空間中去,然后把當(dāng)前空間的內(nèi)存全部回收。

  4. 復(fù)制算法:每次只利用內(nèi)存的一半,當(dāng)內(nèi)存滿時,將存貨對象復(fù)制到另一半中去,這一半內(nèi)存全部回收。

垃圾回收算法并沒有最好的一種,為了達到降低整體GC時間的目的,一般是采用對內(nèi)存分代進行垃圾回收,每個代采用不同的回收算法。

HotSpot堆內(nèi)存分代

  1. 新生代 新生代與老年代內(nèi)存占比默認為1:2。 新生代又可分為Eden區(qū)、Survivor0、Survivor1區(qū),默認占用新生代內(nèi)存比例為8:1:1。

  2. 老年代 老年代是一大塊連續(xù)內(nèi)存,沒有再細分。

HotSpotGC類型

  1. MinorGC,也叫做Young GC,YGC, 是發(fā)生在新生代的GC,當(dāng)Eden區(qū)滿時觸發(fā),HotSpot中新生代均GC采用復(fù)制算法實現(xiàn)。 新分配的對象一般是在Eden區(qū),除非滿足條件時,對象會直接分配到堆上。Eden區(qū)滿之后會將Eden存活對象拷貝到survivor0區(qū)。當(dāng)survivor0內(nèi)存不足時,將survivor0中存活的對象拷貝到survivor1區(qū),并回收survivor0區(qū),然后交換survivor0和survivor1的名稱。一般也叫from和to。 每次從from到to的拷貝,都會記錄對象的年齡+1,當(dāng)對象年齡達到一個設(shè)定的值后(默認15),對象會被分配到老年代。 如果從from向to的拷貝過程中發(fā)現(xiàn)to內(nèi)存不夠用,也會將對象轉(zhuǎn)存到老年代。

直接老年代分配內(nèi)存的情況:

  • 對象所需內(nèi)存大小超過Eden區(qū)大小,所有收集器都支持。

  • Eden區(qū)內(nèi)存不足,且對象所需內(nèi)存大小超過Eden區(qū)一半,直接分配到老年代,且不觸發(fā)MinorGC。使用ParallelScavenge時支持。

  • 對象大小超過XX:PretenureSizeThreshold設(shè)置時,直接進入老年代分配。Serial、ParNew、CMS收集器支持。

  1. FullGC FullGC是發(fā)生在老年代的GC,觸發(fā)時機有:

  • 調(diào)用System.gc()時,系統(tǒng)會建議執(zhí)行GC,但不是立即執(zhí)行。

  • 從新生代晉升到老年代的對象所需內(nèi)存大于老年代可用內(nèi)存時。

GC吞吐量 = 用戶代碼執(zhí)行時間 / (用戶代碼執(zhí)行時間 + GC時間)

HotSpot垃圾收集器

jdk1.7和1.8默認采用ParallelGC,也就是Parallel Scavenge(新生代)+Parallel Old(老年代)GC。 jdk9采用G1垃圾收集器。

其他的垃圾收集器還有CMS、ParaNew、Serial等 查看java默認垃圾收集器命令:

java -XX:+PrintCommandLineFlags -version

-XX:+UseParallelGC 表示使用Parallel Scavenge + Parallel Old
-XX:+UseConcMarkSweepGC 在啟動應(yīng)用加上這個參數(shù)表示使用CMS垃圾收集器
-XX:+UseG1GC 在啟動應(yīng)用時添加這個參數(shù)表示使用G1垃圾收集器,jdk8中支持開啟
Serial、Serial Old

使用單線程進行垃圾回收,GC時停止用于線程工作。單CPU環(huán)境下表現(xiàn)好,因為沒有GC線程間的交互。 Serial用于新生代,復(fù)制算法。Serial Old用于老年代,基于標記-整理

ParNew

Serial的多線程版本,采用復(fù)制算法。在單CPU時不如Serial,多CPU效果較好。 ParNew用于新生代。

Parallel Scavenge

Parallel Scavenge采用復(fù)制算法。算法目的是提高吞吐量,降低GC時間(但可能提升GC次數(shù)),讓用戶代碼得到更多執(zhí)行時機。 Parallel代表并行,即多個GC線程同時進行,但還是會暫停用戶線程,在GC完成后用戶線程才繼續(xù)執(zhí)行。 相比較于ParNew收集器,可以添加啟動參數(shù)XX+UseAdaptiveSizePolicy,添加參數(shù)后可以不用設(shè)置Eden和Survivor區(qū)比例,也不用設(shè)置晉升老年代對象年齡等細節(jié)參數(shù),該算法會自動根據(jù)系統(tǒng)運行情況動態(tài)調(diào)節(jié)參數(shù)。

Parallel Old

Parallel Old是Parallel Scavenge的老年代版本,采用標記-整理算法??梢圆l(fā)GC,整個GC過程是暫停用戶線程執(zhí)行的。

CMS垃圾收集器

CMS全名Concurrent Mark Sweep,并發(fā)標記-回收垃圾收集器。是老年代的GC處理器。 CMS分為四個步驟:

  1. 初始標記:僅標記GCRoots和新生代能夠直接引用到的老年代對象,速度較快,觸發(fā)STW。

  2. 并發(fā)標記:此階段GC標記線程與用戶線程同時執(zhí)行,遍歷初始標記的對象,并遞歸標記這些對象引用的全部對象,這個過程比較慢,但是不觸發(fā)STW。 因為這個階段是并發(fā)標記,可能發(fā)生 對象從新生代晉升到老年代、直接在老年代分配對象、老年代引用對象關(guān)系發(fā)生變化、新生代對老年代對象引用發(fā)生變化 等現(xiàn)象,對于這些對象都是要重新標記的。 做法是將這些對象所在的Card Table中的位設(shè)置為dirty,把并發(fā)標記階段新產(chǎn)生的對象和對象引用關(guān)系的變化記錄下來(記錄到Mod-Union Table)。

Card Table:將老年代內(nèi)存分為相等大小的CardPage,每個CardPage用一個二進制位表示其內(nèi)部的對象在并發(fā)標記階段是否發(fā)生了引用變化,這個二進制位數(shù)組就是CardTable。 Mod-Union Table:是一個和CardTable類似的結(jié)構(gòu); 3. 并發(fā)預(yù)清理:從Mod-Union Table中找到并發(fā)標記階段標記為dirty的內(nèi)存區(qū)域,重新標記這些引用關(guān)系發(fā)生過變化的對象??梢酝ㄟ^參數(shù)CMSPrecleaningEnabled來關(guān)閉這個階段,默認開啟的。
4. 并發(fā)可中斷預(yù)清理:循環(huán)處理From和To區(qū)對象,標記可達的老年代對象;并且循環(huán)處理DirtyCard的標記,不觸發(fā)STW。循環(huán)的退出條件有三種

  1. 循環(huán)次數(shù)超過CMSMaxAbortablePrecleanLoops設(shè)置,默認0,沒有次數(shù)限制;

  2. 循環(huán)時間超過CMSMaxAbortablePrecleanTime設(shè)置,默認5s,超過會退出;

  3. 并發(fā)預(yù)清理時Eden使用率低于10%,而某一次循環(huán)后Eden使用率達到CMSScheduleRemarkEdenPenetration(默認50%)后會退出;

這個階段循環(huán)執(zhí)行的目的是盡量減小下一個重新標記階段需要處理的新生代對象引用老年代對象的情況,因為下一個階段會觸發(fā)STW,為提高吞吐量自然是dirty狀態(tài)的內(nèi)存越少越好。如果剛好在這個循環(huán)執(zhí)行的5秒內(nèi)觸發(fā)了YGC,然后這個階段又并發(fā)了處理了dirty的引用,則下個節(jié)點需要重新標記的對象就沒那么大,STW時間也就短了。 上一個并發(fā)預(yù)清理節(jié)點可以不要的原因就是這一步其實也能達到預(yù)清理的效果,而且是循環(huán)操作的。 5. 重新標記:較慢,CMS的瓶頸點,觸發(fā)STW,并發(fā)重新標記。雖然Preclean和AbortablePreclean已經(jīng)盡量處理了DirtyCard,但是不能保證完全處理掉,因此還需要重新標記,要進行如下處理:

  1. 遍歷新生代對象,重新標記; 這個節(jié)點要遍歷新生代對象,如果新生代使用率很高,對象很多的話會耗時很久去遍歷,因此如果在進行重新標記之前觸發(fā)了YGC,這個步驟的耗時會減少很多。CMS可以通過參數(shù)CMSScavengeBeforeRemark來強制在重新標記階段之前進行一次YGC,該配置默認關(guān)閉。開啟的話可能會出現(xiàn)連續(xù)的兩次YGC,也挺浪費時間。 進行一次YGC之后并不是要把DirtyCard交給重新標記階段的5.3執(zhí)行,而是交給4可中斷預(yù)處理來執(zhí)行。

  2. 遍歷GCRoots,重新標記;

  3. 遍歷DirtyCard,重新標記,這時候經(jīng)過前兩個階段的處理,DirtyCard已經(jīng)減少了很多。

  4. 并發(fā)清除:根據(jù)標記結(jié)果清除垃圾對象,不觸發(fā)STW,速度較慢。

  5. 并發(fā)重置:重置CMS內(nèi)部的數(shù)據(jù),如CardTable、Mod-Uniod Table等,為下一次GC做準備,不觸發(fā)STW。

CMS的兩個標記階段,都會觸發(fā)STW,不一樣之處在于,初始標記僅標記GCRoots和新生代可達的老年代對象,沒有再遞歸遍歷標記,較快完成;而重新標記階段,標記GCRoots、新生代可達、DirtyCard中的老年代對象,且遞歸遍歷標記,比較耗時。

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。


新聞標題:JVM內(nèi)存分區(qū)及GC知識點是什么
本文網(wǎng)址:http://weahome.cn/article/giigho.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部