淺析JVM虛擬機(jī)

1.虛擬機(jī)的組成結(jié)構(gòu)

虛擬機(jī)由類裝載子系統(tǒng)、運(yùn)行時(shí)數(shù)據(jù)區(qū)和執(zhí)行引擎組成

2. 類加載

????①. 什么是類的加載

????????類的加載指的是將類的class文件中的二進(jìn)制數(shù)據(jù)讀入到內(nèi)存中并將其放在運(yùn)行時(shí)數(shù)據(jù)區(qū)的方法區(qū)內(nèi)掌挚,然后在堆區(qū)中創(chuàng)建一個(gè)class對(duì)象,這個(gè)class對(duì)象就是類加載的最終產(chǎn)品

????????類加載是哀澈,創(chuàng)建對(duì)象才會(huì)去加載滓窍,當(dāng)聲明的變量為空或者不創(chuàng)建的時(shí)候,不會(huì)去加載那個(gè)類

????②.類加載過程

????????加載→[(連接)校驗(yàn)→準(zhǔn)備→解析]→初始化→使用→卸載

????????加載:在硬盤上查找并通過IO讀入字節(jié)碼文件到方法區(qū)了赌,使用到的時(shí)候才會(huì)加載(如調(diào)用main()方法或者new對(duì)象)墨榄,加載過程會(huì)執(zhí)行三件事情:

????????一. 通過類的權(quán)限命名來獲取定義的二進(jìn)制字節(jié)流

????????二. 將字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化成方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)

????????三. 到堆里創(chuàng)建類的對(duì)象(方法區(qū)數(shù)據(jù)的訪問入口)

????????連接:執(zhí)行校驗(yàn)、準(zhǔn)備勿她、解析步驟

????????校驗(yàn)(重要非必須):校驗(yàn)字節(jié)碼文件的正確性(-Xverifynone關(guān)閉大部分類驗(yàn)證)袄秩,會(huì)去做四個(gè)校驗(yàn)工作:

????????????一. 檢驗(yàn)文件格式,是否是class文件格式

????????????二. 校驗(yàn)元數(shù)據(jù)逢并,是否符合Java的語言規(guī)范

????????????三. 校驗(yàn)字節(jié)碼播揪,程序是否合法(符合邏輯)

????????????四. 校驗(yàn)符號(hào)引用,保證引用一定被訪問筒狠,不會(huì)出現(xiàn)類無法訪問的問題

????準(zhǔn)備:將符號(hào)引用替換為直接引用,該階段會(huì)把一些靜態(tài)方法(符合引用箱沦,比如main())替換為指向數(shù)據(jù)所存內(nèi)存的指針或句柄(直接引用)辩恼,這就是所謂的靜態(tài)鏈接的過程(類加載期間完成),動(dòng)態(tài)鏈接是在程序運(yùn)行期間完成的符合引用替換為直接引用

????????符號(hào)引用:用一組符號(hào)來描述所引用的目標(biāo)谓形,這組符號(hào)可以是任意形式的字面量灶伊,只要無歧義地定義目標(biāo)

????????符號(hào)引用替換為直接引用:就是將符號(hào)地引用直接替換為地址地引用,在不同虛擬機(jī)地符號(hào)引用是相同的寒跳,但是直接引用地地址可能不同

????初始化:對(duì)類的靜態(tài)變量初始化為指定的值聘萨,執(zhí)行靜態(tài)代碼塊

????③. 類加載器的種類

????????一. 啟動(dòng)類加載器

????????????加載支撐JVM運(yùn)行的位于JRE的lib目錄下的核心類庫,比如rt.jar童太、Charsets.jar等

????????二. 擴(kuò)展類加載器

????????????加載支撐JVM運(yùn)行的位于JRE的lib目錄下的ext擴(kuò)展目錄中的jar類包

????????三. 應(yīng)用程序類加載器

????????????加載ClassPath路徑下的類包米辐,主要就是加載自己寫的那些類

????????四. 自定義加載器

????????????加載用戶自定義路徑下的類包

????????????自定義類加載器:繼承ClassLoader類,當(dāng)我們自定義類加載器時(shí)书释,我們需要重寫findClass方法

????????????雙親委派機(jī)制:加載某個(gè)類時(shí)先委托父加載器尋找目標(biāo)類翘贮,找不到再委托上層父加載器加載,如果所有的父加載器在自己的加載類路徑下都找不到目標(biāo)類爆惧,則在自己的類加載路徑中查找并載入目標(biāo)類

????????如圖:

? ? ? ?在程序中創(chuàng)建的類狸页,如果不做特殊處理,一般是使用應(yīng)用程序類加載器扯再,這四種加載器無繼承關(guān)系但是有父子關(guān)系芍耘,由上到下,由父到子熄阻,當(dāng)我們加載一個(gè)類的時(shí)候斋竞,最開始時(shí)到應(yīng)用程序加載器然后應(yīng)用程序加載器委托給擴(kuò)展類加載器,然后擴(kuò)展類加載器找不到又委托給啟動(dòng)類加載器饺律,啟動(dòng)類加載器如果找不到就又回到應(yīng)用程序類加載器窃页,如果應(yīng)用程序類加載器找到就開始加載

????????為什么要設(shè)計(jì)雙親委派機(jī)制:

????????????(1) 沙箱安全機(jī)制跺株,自己寫的String.class類不會(huì)被加載,這樣便可以防止核心API庫被隨意篡改

????????????(2) 避免類的重復(fù)加載:當(dāng)父親已經(jīng)加載該類時(shí)脖卖,就沒有必要子ClassLoader再加載一次乒省,保證被加載類的唯一性

????????3. Java虛擬機(jī)運(yùn)行時(shí)內(nèi)存區(qū)域劃分

????????????①. 線程私有區(qū)

????????????????一. 程序計(jì)數(shù)器

????????????????????記錄字節(jié)碼執(zhí)行行號(hào)(注意:這個(gè)地方只計(jì)數(shù),不會(huì)產(chǎn)生內(nèi)存溢出)

????????????????二. 虛擬機(jī)棧(線程棧)

? ? ? ? ? ? ? ? ? ? ?當(dāng)Java中的方法被執(zhí)行時(shí)畦木,會(huì)形成棧幀進(jìn)入棧中袖扛,這種行為成為壓棧,反之則會(huì)彈出十籍,稱為彈棧蛆封。棧內(nèi)存結(jié)構(gòu),如圖:

????????????????????每一個(gè)方法會(huì)在對(duì)應(yīng)的棧中開辟一塊棧幀的內(nèi)存空間

????????????????????棧幀又分為局部變量表勾栗,操作數(shù)棧惨篱,方法出口等一系列區(qū)域

????????????????????????????局部變量表:存放局部變量

????????????????????????????操作數(shù)棧:當(dāng)我們的值入棧之后,先到這個(gè)地方围俘,然后再轉(zhuǎn)到局部變量砸讳,例如:棧幀中有int a = 1,那最開始操作數(shù)棧存放1界牡,然后再在局部變量表里存放a = 1簿寂,類似于中轉(zhuǎn)站,臨時(shí)存儲(chǔ)數(shù)據(jù)

????????????????????????????動(dòng)態(tài)鏈接:在程序期間將符號(hào)引用替換為直接地址引用

????????????????????????????方法出口:存儲(chǔ)方法一些返回信息

????????????????????三. 本地方法棧

? ? ? ? ? ? ?②. 線程共享區(qū)

? ? ? ? ? ? ? ? ? ?一. 堆內(nèi)存

????????????????????????分配所有對(duì)象實(shí)例宿亡,垃圾回收工作的主要區(qū)域常遂,一般情況下,堆內(nèi)存是所有內(nèi)存區(qū)域中最大的區(qū)域

????????????????????二. 元數(shù)據(jù)區(qū)(方法區(qū))

????????????????????????????虛擬機(jī)加載的類元信息挽荠,常量克胳,靜態(tài)變量

????????????????????????????方法區(qū)使用的是系統(tǒng)的直接內(nèi)存

????????????????????????????類元信息:類型信息、類型的常量池圈匆、字段信息毯欣、方法信息、類變量臭脓、指向類加載的引用酗钞、指向class實(shí)例的引用、方法表

????????????????????三.直接內(nèi)存

????????????????????????????嚴(yán)格意義上并不屬于JVM的內(nèi)存来累,非JVM內(nèi)存的堆外內(nèi)存砚作,非阻塞io會(huì)直接操作這塊內(nèi)存,提升讀寫數(shù)據(jù)的效率嘹锁,如nio

? ? ? 4. JVM的內(nèi)存模型

? ?5. JVM內(nèi)存分配和回收策略

????????默認(rèn)情況下年輕代占堆內(nèi)存的1/3葫录,老年區(qū)占2/3

????????①. 對(duì)象優(yōu)先在Eden區(qū)分配

????????????????首先new出來的對(duì)象都分配在堆內(nèi)存,堆內(nèi)存分為老年代领猾,年輕代(分為Eden區(qū)米同、Survivor區(qū)[分為from區(qū)和to區(qū)])骇扇,多數(shù)情況下對(duì)象在Eden區(qū)分配,當(dāng)Eden區(qū)沒有足夠空間進(jìn)行分配時(shí)面粮,虛擬機(jī)會(huì)發(fā)起一次Minor GC

Minor GC和Full GC有什么不同

Minor GC/Young GC:指發(fā)生在新生代的垃圾回收動(dòng)作少孝,操作比較頻繁,并且速度相對(duì)較快

Major GC/Full GC:一般會(huì)回收老年代熬苍,年輕代稍走,方法區(qū)的垃圾,速度比Minor GC慢十倍以上

????????????②. 大對(duì)象直接進(jìn)入老年代

????????????????大對(duì)象就是需要連續(xù)內(nèi)存空間的對(duì)象柴底,如:字符串婿脸,數(shù)組

? ? ? ? ? ? ? ? JVM可以通過參數(shù)(-XX:PretenureSizeThreshold)設(shè)置參數(shù)的大小,如果對(duì)象超過設(shè)置值的大小就會(huì)直接進(jìn)入老年代柄驻,這個(gè)參數(shù)只在Serial和ParNew兩個(gè)數(shù)據(jù)期下有效

????????????????為什么大對(duì)象直接進(jìn)入老年代

????????????????????????為了避免大對(duì)象在分配內(nèi)存時(shí)的賦值操作而降低效率

????????????③. 長(zhǎng)期存活的對(duì)象將進(jìn)入老年代

? ? ? ? ? ? ? ? ? ?虛擬機(jī)會(huì)給每一個(gè)對(duì)象一個(gè)年齡計(jì)數(shù)器狐树,如果對(duì)象在Eden區(qū)出生并經(jīng)過第一次Minor GC后能夠存活并且能被Survivor容納將被移動(dòng)到Survivor空間中并且對(duì)象年齡設(shè)為1對(duì)象在Survivor中每經(jīng)過一次minor GC就會(huì)把年齡加一,當(dāng)年齡提升到一定程度鸿脓,默認(rèn)15褪迟,就會(huì)進(jìn)入到老年代

????????????????????既然虛擬機(jī)采用了分代收集的思想來管理內(nèi)存,那么內(nèi)存回收時(shí)就必須能識(shí)別哪些對(duì)象應(yīng)放在新生代答憔,哪些對(duì)象應(yīng)放在老年代。為了做到這一點(diǎn)掀抹,虛擬機(jī)給每個(gè)對(duì)象一個(gè)對(duì)象年齡(Age)計(jì)數(shù)器

????????????????????如果對(duì)象在Eden區(qū)出生并經(jīng)過第一次Minor GC之后仍然能夠存活虐拓,并且能被Survivor容納的話,將被移動(dòng)到Survivor空間中傲武,并將對(duì)象年齡設(shè)為1蓉驹,對(duì)象在Survivor中沒經(jīng)過一次Minor GC,年齡就增加1歲疚顷,當(dāng)它的年齡增長(zhǎng)到一定程度(默認(rèn)時(shí)15歲)端幼,就會(huì)被晉升到老年代蓄氧,對(duì)象晉升到老年代的年齡閥值,可通過參數(shù)-XX:MaxTenuringThreshold來設(shè)置

????????????④. Minor GC之后存活下來的對(duì)象在Survivor中放不下瞻润,那這個(gè)對(duì)象的一部分會(huì)去老年代一部分會(huì)去Survivor區(qū)

????????????⑤. Eden區(qū)和Survivor區(qū)的比例默認(rèn)是8:1:1

????????????????大量的對(duì)象被分配在Eden區(qū),當(dāng)Eden區(qū)滿了之后會(huì)觸發(fā)minor GC甜刻,可能有百分之九十的對(duì)象會(huì)被認(rèn)為是垃圾被回收掉绍撞,剩余存活的對(duì)象會(huì)被移動(dòng)到Survivor區(qū),因?yàn)樾律膶?duì)象幾乎都是朝生夕死的得院,所以Eden區(qū)足夠大傻铣,Survivor區(qū)夠用即可

????????????⑥. 對(duì)象動(dòng)態(tài)年齡判斷

????????????????????如果當(dāng)前存放對(duì)象的Survivor區(qū)域里一批對(duì)象的總大小大于這塊Survivor內(nèi)存區(qū)域大小的百分之五十,那么此時(shí)大于等于這批對(duì)象年齡最大值的對(duì)象就可以直接進(jìn)入老年代

????????????????????這個(gè)規(guī)則其實(shí)是希望那些可能長(zhǎng)期存活的對(duì)象祥绞,今早進(jìn)入老年代

????????????????????對(duì)象動(dòng)態(tài)年齡判斷機(jī)制一般是在Minor GC之后觸發(fā)的

????????????⑦. 老年代空間分配擔(dān)保機(jī)制

????????????????新生代在每一次Minor GC之前非洲,JVM都會(huì)計(jì)算下老年代的剩余空間鸭限,如果老年代剩余可用空間小于年輕代里現(xiàn)有的所有對(duì)象大小之和(包括垃圾對(duì)象),就會(huì)查看HandlePromotionFailure這個(gè)參數(shù)是否設(shè)置(jdk1.8默認(rèn)設(shè)置)两踏,如果這個(gè)參數(shù)已經(jīng)設(shè)置败京,就會(huì)查看老年代的剩余可用空間是否大于每次Minor GC后進(jìn)入老年代的對(duì)象平均大小,如果是參數(shù)未設(shè)置缆瓣,或者是小于這個(gè)評(píng)價(jià)大小喧枷,就會(huì)觸發(fā)一次Full GC

????????????????老年代空間擔(dān)保機(jī)制整體過程如圖:

????????????????如果回收完還是沒有足夠空間存放新的對(duì)象,就會(huì)發(fā)生OOM

6. Java虛擬機(jī)如何判斷對(duì)象是否存活

????①.引用計(jì)數(shù)法

????????如果對(duì)象A具有引用計(jì)數(shù)器弓坞,當(dāng)對(duì)象B對(duì)A產(chǎn)生引用時(shí)隧甚,那計(jì)數(shù)器的值會(huì)+1,當(dāng)引用斷開時(shí)渡冻,計(jì)數(shù)器的值-1戚扳,但是會(huì)出現(xiàn)當(dāng)AB循環(huán)引用時(shí),引用計(jì)數(shù)器的值將無法為0

? ? ? ? ?引用計(jì)數(shù)法判斷回收:給對(duì)象中添加一個(gè)引用計(jì)數(shù)器族吻,每當(dāng)有一個(gè)地方引用它帽借,計(jì)數(shù)器就+1;當(dāng)引用失效超歌,計(jì)數(shù)器-1砍艾;任何時(shí)候計(jì)數(shù)器為0的對(duì)象就是不可能再被使用的。當(dāng)對(duì)象引用計(jì)數(shù)器為0時(shí)巍举,即無其他對(duì)象引用脆荷,判定為死亡,可被回收懊悯,但是存在循環(huán)引用問題蜓谋,導(dǎo)致對(duì)象一直存活,無法被回收

????②. 可達(dá)性分析法

????????從GC Root根開始一直向下查找炭分,直接或間接找到對(duì)象桃焕,稱為可達(dá),反之則不可達(dá)捧毛,這個(gè)算法的基本思想是通過一系列稱為“GC Root”的對(duì)象作為起始點(diǎn)观堂,從這些節(jié)點(diǎn)向下搜索,找到的對(duì)象標(biāo)記為非垃圾對(duì)象呀忧,其余未標(biāo)記的對(duì)象都是垃圾都想

????????可達(dá)性分析法判斷回收:從GC Root根開始向下搜索型将,直接或間接可達(dá)的對(duì)象,即存活對(duì)象

????????可被作為GC Root的對(duì)象:虛擬機(jī)棧引用對(duì)象荐虐,本地方法棧引用對(duì)象七兜,靜態(tài)屬性引用對(duì)象,常量引用對(duì)象

????????對(duì)象引用的分類:

????????????一.強(qiáng)引用

????????????????程序中普遍存在的對(duì)象引用

????????????二. 軟引用

????????????????SoftReference實(shí)現(xiàn)福扬,內(nèi)存溢出前回收腕铸,將對(duì)象用SoftReference軟引用類型的對(duì)象包裹惜犀,正常情況不會(huì)被回收,但是GC做完后發(fā)現(xiàn)是放不出空間存放新的對(duì)象狠裹,則會(huì)把這些軟引用對(duì)象回收掉虽界。軟引用可用來實(shí)現(xiàn)對(duì)內(nèi)存敏感度不高的高速緩存

????????????????public static SoftReference<User> user = new SoftReference<User>(new User());

????????????三. 弱引用

????????????????WeakReference實(shí)現(xiàn),下一次垃圾回收時(shí)被回收,將對(duì)象用WeakReference弱引用類型的對(duì)象包裹涛菠,弱引用跟沒引用差不多莉御,GC會(huì)直接回收掉,很少用

????????????????public static WeakReference<User> user = new WeakReference<User>(new User());

????????????四. 虛引用

????????????????PhantomReference實(shí)現(xiàn)俗冻,形同虛設(shè)礁叔,沒有具體的作用,虛引用也被稱為幽靈引用或者幻影引用迄薄,它是最弱的一種引用關(guān)系琅关,幾乎不用

? ? ? ?③. finalize()方法最終判定對(duì)象是否存活

????????????對(duì)象不可達(dá)、沒有與GC Root根相連接的對(duì)象會(huì)調(diào)用finalize()方法

????????????即使再可達(dá)性分析算法中不可達(dá)的對(duì)象讥蔽,也并非“非死不可”涣易,這時(shí)候它們暫時(shí)處于“緩刑”階段,要真正宣告一個(gè)對(duì)象死亡冶伞,至少要經(jīng)歷再次標(biāo)記過程

????????????標(biāo)記的前提是對(duì)象再進(jìn)行可達(dá)性分析后發(fā)現(xiàn)沒有GC Root相連接的引用鏈

????????????第一次標(biāo)記并進(jìn)行篩選:對(duì)象沒有覆蓋finalize()方法新症,對(duì)象直接被回收

????????????第二次標(biāo)記:如果這個(gè)對(duì)象覆蓋了finalize()方法,只要重新與引用鏈上的任何一個(gè)對(duì)象建立關(guān)聯(lián)即可

????????④. 對(duì)象怎樣起死回生?

????????????當(dāng)對(duì)象A被標(biāo)記為不可達(dá)時(shí)响禽,首先要進(jìn)行篩選,是否覆蓋finalize()方法徒爹,并且finalize()有沒有被調(diào)用過,如果沒有會(huì)放到F-Queue里面金抡,JVM會(huì)啟動(dòng)進(jìn)程進(jìn)行重新標(biāo)記,也就是說對(duì)象在finalize()方法中重新與引用鏈上任意一個(gè)對(duì)象建立關(guān)聯(lián)即可腌且。不建議這么做梗肝,首先是運(yùn)行代價(jià)太高,其次是不確定性大铺董,無法保證對(duì)象調(diào)用順序

????????⑤. 如何判斷對(duì)象可以被回收巫击,判斷一個(gè)類是無用的類

????????????類需要同時(shí)滿足三個(gè)條件才能算“無用的類”:

????????????(1)該類所有的實(shí)例都已被回收,也就是堆中不存在該類的任何實(shí)例

????????????(2) 加載該類的ClassLoader已經(jīng)被回收

????????????(3) 該類對(duì)應(yīng)的java.lang.Class對(duì)象沒有在任何地方被引用精续,無法在任何地方通過反射訪問該類的方法

7.四種回收算法

????????(1) 標(biāo)記-清除算法

????????????首先標(biāo)記出所有需要回收的對(duì)象坝锰,標(biāo)記完成后統(tǒng)一回收,但是這種方式會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片重付,當(dāng)有大對(duì)象需要分配連續(xù)內(nèi)存空間時(shí)顷级,有可能會(huì)觸發(fā)再次垃圾回收

????????(2) 標(biāo)記-整理算法

????????????首先標(biāo)記出所有需要回收的對(duì)象,在回收對(duì)象之后确垫,會(huì)集中整理內(nèi)存區(qū)域弓颈,得到比較規(guī)整的內(nèi)存區(qū)域帽芽,這種方式可以避免大量的內(nèi)存碎片,但是整體的效率較低

????????(3) 復(fù)制算法

????????????復(fù)制算法是將內(nèi)存分為大小相等的兩塊翔冀,當(dāng)一塊內(nèi)存已經(jīng)用完导街,就將還活著的對(duì)象復(fù)制到另一塊上,然后再把使用過的內(nèi)存空間一次性清理纤子,優(yōu)點(diǎn)是:效率高,沒碎片搬瑰,適合朝生夕死的內(nèi)存區(qū)域。缺點(diǎn)是:內(nèi)存利用低控硼,且不適合在對(duì)象存活率高的老年代使用

????????(4) 分代回收算法(JVM使用)

????????????對(duì)于新生代使用的是復(fù)制算法泽论,對(duì)內(nèi)存劃分為8:1:1的部分,對(duì)于老年代/元數(shù)據(jù)區(qū)的對(duì)象長(zhǎng)期存活的區(qū)域象颖,采用的是標(biāo)記-清除/整理算法

8. JVM垃圾收集器

????如果說垃圾收集算法是內(nèi)存回收的方法論佩厚,垃圾收集器就是內(nèi)存回收的具體實(shí)現(xiàn)

如圖展示了七種作用于不同分代的收集器,如果兩個(gè)收集器之間又連線说订,就說明他們可以搭配使用

????①. Serial收集器(新生代使用:-XX:+UseSerialGC 老年代使用:-XX:+UseSerialOldGC)

????????Serial收集器是一種單線程的收集器抄瓦,單線程一般意味著他只用一個(gè)CPU或一條線程去完成垃圾手機(jī)工作,另一方面陶冷,意味著他在進(jìn)行垃圾回收工作時(shí)钙姊,必須暫停其他線程的所有工作,也就是stop the word直到他收集結(jié)束為止埂伦,為了應(yīng)對(duì)stop the word 產(chǎn)生的不良影響煞额,在后續(xù)的迭代中,線程暫停的時(shí)間越來越短沾谜,serial垃圾回收器采用的回收算法是:新生代采用復(fù)制算法膊毁,老年代采用標(biāo)記-整理算法

????????優(yōu)點(diǎn):簡(jiǎn)單、高效基跑,沒有了多線程之間的線程交互開銷婚温,讓單線程更加高效地進(jìn)行收集工作

????????serial收集器工作流程

????????????Serial Old(MSC)是serial收集器地老年代版本,同樣是一個(gè)單線程收集器媳否,主要有兩大用途栅螟,一種是在JDK1.5以及以前版本中Parallel Scavenge收集器搭配使用,第二種是作為CMS收集器地后備方案

????②.ParNew收集器(-XX:+UseParNewGC)

????????????ParNew收集器篱竭,其實(shí)就是Serial收集器的多線程版本力图,除了使用多線程進(jìn)行垃圾收集外,其余行為如回收參數(shù)掺逼,收集算法吃媒,回收策略等和Serial收集器完全一樣

????????????ParNew垃圾回收器采用的回收算法是:新生代采用復(fù)制算法,老年代采用標(biāo)記-整理算法

????????????ParNew收集器默認(rèn)的線程數(shù)和CPU的核數(shù)相同,也可以用ParallelGCThreads指定線程收集數(shù)一般不推薦修改

????????????ParNew收集器一般是運(yùn)行在Server模式下的虛擬機(jī)的首要選擇晓折,除了Serial收集器外惑朦,只有他能與CMS收集器配合工作

????????③. Parallel Scavenge收集器(新生代使用:-XX:+UseParallelGC 老年代使用:-XX:+UseParallelOldGC)

????????????Parallel Scavenge收集器類似于ParNew收集器,是Server模式(內(nèi)存大于2G漓概,2個(gè)CPU)下的默認(rèn)收集器

????????????Parallel Scavenge的特點(diǎn):Parallel Scavenge的主要特點(diǎn)是吞吐量(高效率地利用CPU)漾月,吞吐量=運(yùn)行用戶代碼時(shí)間/(運(yùn)行云湖代碼時(shí)間+垃圾手機(jī)時(shí)間),他提供了很多參數(shù)胃珍,供用戶找到最合適地停頓時(shí)間或最大吞吐量

????????????Parallel Scavenge垃圾回收器采用的回收算法是:新生代采用復(fù)制算法梁肿,老年代采用標(biāo)記-整理算法

????????????如果對(duì)于垃圾回收不是很了解,或者在優(yōu)化比較困難地時(shí)候觅彰,使用Parallel Scavenge收集器配合自適應(yīng)調(diào)節(jié)策略吩蔑,把內(nèi)存管理地調(diào)優(yōu)任務(wù)交給虛擬機(jī)去完成將會(huì)是一個(gè)不錯(cuò)地選擇

????????????Parallel Old收集器,是Parallel Scavenge收集器地老年代版本填抬,使用多線程和標(biāo)記-整理算法烛芬,在注重吞吐量以及CPU資源地場(chǎng)合,都可以優(yōu)先考慮Parallel Scavenge收集器和Parallel Old收集器

????????④.CMS收集器(-XX:+UseConcMarkSweepGC老年代)

????????????CMS:Conrrurent Mark Sweep飒责,是指以最短回收停頓時(shí)間為目標(biāo)的收集器赘娄,他非常符合在注重用戶體驗(yàn)的應(yīng)用上使用,他是HotSpot虛擬機(jī)第一款真正意義上的并發(fā)收集器宏蛉,它是以標(biāo)記-清除算法實(shí)現(xiàn)的遣臼,它的運(yùn)作過程,相對(duì)于前面幾種垃圾收集器更加復(fù)雜拾并,分為四步:

????????????一.初始標(biāo)記:暫停其他所有的線程并標(biāo)記GC Root能直接關(guān)聯(lián)到的對(duì)象揍堰,時(shí)間很短

????????????二. 并發(fā)標(biāo)記:同時(shí)開啟GC和用戶線程,用一個(gè)閉包結(jié)構(gòu)去記錄可達(dá)對(duì)象嗅义,但當(dāng)這個(gè)步驟結(jié)束屏歹,這個(gè)閉包結(jié)構(gòu)并不一定包含所有可達(dá)對(duì)象,因?yàn)橛脩艟€程會(huì)不斷地更新引用域之碗,所以GC線程無法實(shí)時(shí)地分析對(duì)象的可達(dá)性蝙眶,所以這個(gè)算法里會(huì)跟蹤記錄發(fā)生引用更新的地方

并發(fā)標(biāo)記過程占用整個(gè)GC70%-80%的時(shí)間

????????????三. 重新標(biāo)記:修正并發(fā)標(biāo)記期間因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記長(zhǎng)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄,這個(gè)階段停頓時(shí)間比初始階段稍長(zhǎng)

????????????四. 并發(fā)清除:開啟用戶線程继控,同時(shí)GC線程開始對(duì)未標(biāo)記的區(qū)域作清掃械馆,時(shí)間很長(zhǎng)

????????????優(yōu)點(diǎn): 并發(fā)收集胖眷、低停頓

????????????缺點(diǎn):

????????????????一. 對(duì)CPU資源敏感

????????????????二. 無法處理浮動(dòng)垃圾

????????????????三. 它使用的回收算法是標(biāo)記-清除算法武通,會(huì)有大量空間碎片產(chǎn)生,當(dāng)然通過參數(shù)-XX:+UseCMSCompactAtFullCollection可以讓JVM在執(zhí)行完標(biāo)記-清除后再做一次整理

????????????????四. 執(zhí)行過程中的不確定性珊搀,會(huì)存在上一次垃圾回收還沒有執(zhí)行完冶忱,然后垃圾回收又被觸發(fā)的情況,特別是在并發(fā)標(biāo)記和并發(fā)清理時(shí)出現(xiàn)境析,一邊回收囚枪,系統(tǒng)一邊運(yùn)行派诬,也許沒回收完就再次觸發(fā)Full GC,也就是‘concurrent mode failure’,此時(shí)進(jìn)入Stop The Word(停止所有用戶線程)链沼,用Serial Old垃圾收集器來回收

????????相關(guān)參數(shù):

????????????(1)-XX:+UseConcMarkSweepGC:啟用CMS

????????????(2) -XX:ConcGCThread:并發(fā)的GC線程數(shù)

????????????(3) -XX:+UseCMSCompactAtFullCollection:Full GC之后做壓縮整理(減少碎片)

????????????(4) -XX:CMSFullGCBeforeCompaction:多少次Full GC之后壓縮一次默赂,默認(rèn)是0,代表每次Full GC之后都會(huì)壓縮一次

????????????(5) -XX:CMSInitiatingOccupancyFraction:當(dāng)老年代使用達(dá)到該比例時(shí)會(huì)觸發(fā)Full GC(默認(rèn)是92括勺,這是百分比)

????????????(6) -XX:+UseCMSInitiatingOccupancyOnly:只是用設(shè)定的回收閥值(-XX:CMSInitiatingOccupancyFraction設(shè)定的值)缆八,如果不指定,JVM在第一次使用設(shè)定值疾捍,后續(xù)會(huì)自動(dòng)調(diào)整

????????????(7) -XX:+CMSScavengeBeforeRemark:在CMS GC前啟動(dòng)一次minor GC奈辰,目的在于減少老年代對(duì)新生代的引用,降低CMS GC的標(biāo)記階段時(shí)的開銷乱豆,一般CMS的GC好事80%都在標(biāo)記階段

????⑤. G1收集器(-XX:+UseG1GC)

????????????G1:Garbage-Frist奖恰,是一款面向服務(wù)器的收集器,主要針對(duì)配備多顆處理器及大容量?jī)?nèi)存的機(jī)器以及高概率滿足GC挺短時(shí)間要求的同時(shí)宛裕,還具備高吞吐量性能特征

基本特性:

????一. 將堆劃分為多個(gè)大小相等的獨(dú)立區(qū)域(Region瑟啃,JVM最多含有2048個(gè)Region)

????二. 一般Region大小等于堆大小除以2048

????三. 保留了年輕代和老年代的概念,但不再物理隔閡了续滋,他們都是(可以不連續(xù))Region的集合

????四. 默認(rèn)年輕代對(duì)堆內(nèi)存的占比是5%

????五. Region的區(qū)域功能可能會(huì)動(dòng)態(tài)變化翰守,一個(gè)Region可能之前是年輕代,垃圾回收之后又可能變成了老年代

????G1對(duì)大對(duì)象的處理:G1有專門分配大對(duì)象的Region叫Humongous區(qū)疲酌,在G1中蜡峰,大對(duì)象的判定規(guī)則是一個(gè)大對(duì)象超過了一個(gè)Region大小的50%,F(xiàn)ull GC回收該區(qū)對(duì)象

????G1垃圾收集過程

????????一. 初始標(biāo)記(STW):暫停其他所有的線程朗恳,并記錄下GC Root直接引用的對(duì)象湿颅,速度很快

????????二.并發(fā)標(biāo)記:用一個(gè)閉包結(jié)構(gòu)去記錄可達(dá)對(duì)象,跟蹤記錄發(fā)生引用的地方

????????三. 最終標(biāo)記(STW):修正并標(biāo)記期間因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記長(zhǎng)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄

????????四. 篩選回收(STW):首先對(duì)各個(gè)Region的回收價(jià)值和成本進(jìn)行排序粥诫,根據(jù)用戶所期望的GC停頓時(shí)間(可以用JVM參數(shù)-XX:MaxGCPauseMillis來指定)來制定回收計(jì)劃

????G1垃圾收集分類:

????????(1) Young GC:Young GC并不是說現(xiàn)有的Eden區(qū)放滿了就會(huì)馬上觸發(fā)油航,G1會(huì)計(jì)算下現(xiàn)在Eden區(qū)回收大概要多久時(shí)間,如果回收時(shí)間遠(yuǎn)遠(yuǎn)小于參數(shù)-XX:MaxGCPauseMillis設(shè)置的值怀浆,那么增加年輕代的Region谊囚,繼續(xù)給新對(duì)象存放,不會(huì)馬上做Young GC执赡,知道下一次Eden區(qū)放滿镰踏,G1計(jì)算回收時(shí)間接近參數(shù)-XX:MaxGCPauseMillis設(shè)置的值,那么就會(huì)觸發(fā)Young GC

????????(2)Mixed GC:不是Full GC沙合,老年代的堆占有率達(dá)到參數(shù)(-XX:InitiatingHeapOccupancyPercent)設(shè)置的值則會(huì)觸發(fā)奠伪,回收所有的Young和部分Old(根據(jù)期望的GC停頓時(shí)間確定Old區(qū)垃圾收集的優(yōu)先順序)以及大對(duì)象區(qū)

????????(3) Full GC:停止系統(tǒng)程序,然后采用單線程進(jìn)行標(biāo)記,清理和壓縮整理绊率,空閑出來一批Region來供下一次Mixed GC使用谨敛,這個(gè)過程非常耗時(shí)

? 9. 逃逸分析

????JVM三種運(yùn)行模式

????????①.解釋模式(Interpreted Model):只使用解釋器(-Xint強(qiáng)制JVM使用解釋模式),執(zhí)行一行JVM字節(jié)碼編譯一行為機(jī)器碼

????????②. 編譯模式(Compiled Model):只是用編譯器(-Xcomp JVM使用編譯模式)滤否,先將所有JVM字節(jié)碼一次性編譯為機(jī)器碼脸狸,然后一次性執(zhí)行所有機(jī)器碼

????????③.混合模式(Mixed Model):依然使用解釋模式執(zhí)行代碼,但是對(duì)于一些“熱點(diǎn)”代碼采用編譯模式執(zhí)行,JVM一般采用混合模式執(zhí)行代碼

對(duì)象逃逸分析:就是分析對(duì)象動(dòng)態(tài)作用域藐俺,當(dāng)一個(gè)對(duì)象在方法中被定義后肥惭,它可能被外部方法所引用,例如作為調(diào)用參數(shù)傳遞到其他地方中

(設(shè)置參數(shù):開啟:-XX:+DoEscapeAnalysis 關(guān)閉:-XX:-DoEscapeAnalysis)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末紊搪,一起剝皮案震驚了整個(gè)濱河市蜜葱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌耀石,老刑警劉巖牵囤,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異滞伟,居然都是意外死亡揭鳞,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門梆奈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來野崇,“玉大人,你說我怎么就攤上這事亩钟∨依妫” “怎么了?”我有些...
    開封第一講書人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵清酥,是天一觀的道長(zhǎng)扶镀。 經(jīng)常有香客問我,道長(zhǎng)焰轻,這世上最難降的妖魔是什么臭觉? 我笑而不...
    開封第一講書人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮辱志,結(jié)果婚禮上蝠筑,老公的妹妹穿的比我還像新娘。我一直安慰自己揩懒,他們只是感情好什乙,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著旭从,像睡著了一般稳强。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上和悦,一...
    開封第一講書人閱讀 52,584評(píng)論 1 312
  • 那天退疫,我揣著相機(jī)與錄音,去河邊找鬼鸽素。 笑死褒繁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的馍忽。 我是一名探鬼主播棒坏,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼遭笋!你這毒婦竟也來了坝冕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤瓦呼,失蹤者是張志新(化名)和其女友劉穎喂窟,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體央串,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡磨澡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了质和。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稳摄。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖饲宿,靈堂內(nèi)的尸體忽然破棺而出厦酬,到底是詐尸還是另有隱情,我是刑警寧澤瘫想,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布弃锐,位于F島的核電站,受9級(jí)特大地震影響殿托,放射性物質(zhì)發(fā)生泄漏霹菊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一支竹、第九天 我趴在偏房一處隱蔽的房頂上張望旋廷。 院中可真熱鬧,春花似錦礼搁、人聲如沸饶碘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽扎运。三九已至瑟曲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間豪治,已是汗流浹背洞拨。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留负拟,地道東北人烦衣。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像掩浙,于是被迫代替她去往敵國和親花吟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 1.問題 1矾麻、JAVA文本文件如何被翻譯成CLASS二進(jìn)制文件? 2、如何理解CLASS文件的組成結(jié)構(gòu)芭梯? 3险耀、虛擬...
    java成功之路閱讀 308評(píng)論 1 0
  • 一、運(yùn)行時(shí)數(shù)據(jù)區(qū)域 程序計(jì)數(shù)器Java 虛擬機(jī)棧本地方法棧堆方法區(qū)運(yùn)行時(shí)常量池直接內(nèi)存 二玖喘、垃圾收集 判斷一個(gè)對(duì)象...
    Java機(jī)械師閱讀 726評(píng)論 0 1
  • 1. 垃圾回收機(jī)制 Stop-the-World:JVM由于要執(zhí)行GC而停止了應(yīng)用程序的執(zhí)行稱之為Stop-the...
    無痕25閱讀 312評(píng)論 0 0
  • JVM有哪些分區(qū)甩牺?程序計(jì)數(shù)器,java虛擬機(jī)棧累奈,本地方法棧贬派,堆,方法區(qū)澎媒。 java棧中存放的是一個(gè)個(gè)棧幀搞乏,每一個(gè)棧...
    irckwk1閱讀 697評(píng)論 0 0
  • Java內(nèi)存區(qū)域 說一下 JVM 的主要組成部分及其作用? JVM包含兩個(gè)子系統(tǒng)和兩個(gè)組件戒努,兩個(gè)子系統(tǒng)為Class...
    老pao說Java閱讀 805評(píng)論 1 14