JVM架構(gòu)和GC垃圾回收機(jī)制詳解

JVM架構(gòu)圖分析

JVM被分為三個(gè)主要的子系統(tǒng)

(1)類(lèi)加載器子系統(tǒng)(2)運(yùn)行時(shí)數(shù)據(jù)區(qū)(3)執(zhí)行引擎

1. 類(lèi)加載器子系統(tǒng)

Java的動(dòng)態(tài)類(lèi)加載功能是由類(lèi)加載器子系統(tǒng)處理碱工。當(dāng)它在運(yùn)行時(shí)(不是編譯時(shí))首次引用一個(gè)類(lèi)時(shí)帆离,它加載眨攘、鏈接并初始化該類(lèi)文件。

1.1 加載

類(lèi)由此組件加載六荒。啟動(dòng)類(lèi)加載器 (BootStrap class Loader)阅懦、擴(kuò)展類(lèi)加載器(Extension class Loader)和應(yīng)用程序類(lèi)加載器(Application class Loader) 這三種類(lèi)加載器幫助完成類(lèi)的加載搔弄。

  1. 啟動(dòng)類(lèi)加載器 – 負(fù)責(zé)從啟動(dòng)類(lèi)路徑中加載類(lèi),無(wú)非就是rt.jar文兑。這個(gè)加載器會(huì)被賦予最高優(yōu)先級(jí)盒刚。

  2. 擴(kuò)展類(lèi)加載器 – 負(fù)責(zé)加載ext 目錄(jre\lib)內(nèi)的類(lèi).

  3. 應(yīng)用程序類(lèi)加載器 – 負(fù)責(zé)加載應(yīng)用程序級(jí)別類(lèi)路徑,涉及到路徑的環(huán)境變量等etc.

上述的類(lèi)加載器會(huì)遵循委托層次算法(Delegation Hierarchy Algorithm)加載類(lèi)文件彩届。

1.2 鏈接

  1. 校驗(yàn) – 字節(jié)碼校驗(yàn)器會(huì)校驗(yàn)生成的字節(jié)碼是否正確伪冰,如果校驗(yàn)失敗,我們會(huì)得到校驗(yàn)錯(cuò)誤樟蠕。

  2. 準(zhǔn)備 – 分配內(nèi)存并初始化默認(rèn)值給所有的靜態(tài)變量贮聂。

  3. 解析 – 所有符號(hào)內(nèi)存引用方法區(qū)(Method Area)原始引用所替代。

1.3 初始化

這是類(lèi)加載的最后階段寨辩,這里所有的靜態(tài)變量會(huì)被賦初始值, 并且靜態(tài)塊將被執(zhí)行吓懈。

2. 運(yùn)行時(shí)數(shù)據(jù)區(qū)(Runtime Data Area)

The 運(yùn)行時(shí)數(shù)據(jù)區(qū)域被劃分為5個(gè)主要組件:

2.1 方法區(qū)(Method Area)

所有類(lèi)級(jí)別數(shù)據(jù)將被存儲(chǔ)在這里,包括靜態(tài)變量靡狞。每個(gè)JVM只有一個(gè)方法區(qū)耻警,它是一個(gè)共享的資源。

2.2 堆區(qū)(Heap Area)

所有的對(duì)象和它們相應(yīng)的實(shí)例變量以及數(shù)組將被存儲(chǔ)在這里甸怕。每個(gè)JVM同樣只有一個(gè)堆區(qū)甘穿。由于方法區(qū)堆區(qū)的內(nèi)存由多個(gè)線程共享,所以存儲(chǔ)的數(shù)據(jù)不是線程安全的梢杭。

2.3 棧區(qū)(Stack Area)

對(duì)每個(gè)線程會(huì)單獨(dú)創(chuàng)建一個(gè)運(yùn)行時(shí)棧温兼。對(duì)每個(gè)函數(shù)呼叫會(huì)在棧內(nèi)存生成一個(gè)棧幀(Stack Frame)。所有的局部變量將在棧內(nèi)存中創(chuàng)建武契。棧區(qū)是線程安全的募判,因?yàn)樗皇且粋€(gè)共享資源。棧幀被分為三個(gè)子實(shí)體:

a 局部變量數(shù)組 – 包含多少個(gè)與方法相關(guān)的局部變量并且相應(yīng)的值將被存儲(chǔ)在這里咒唆。

b 操作數(shù)棧 – 如果需要執(zhí)行任何中間操作届垫,操作數(shù)棧作為運(yùn)行時(shí)工作區(qū)去執(zhí)行指令。

c 幀數(shù)據(jù) – 方法的所有符號(hào)都保存在這里全释。在任意異常的情況下装处,catch塊的信息將會(huì)被保存在幀數(shù)據(jù)里面。

2.4 PC寄存器

每個(gè)線程都有一個(gè)單獨(dú)的PC寄存器來(lái)保存當(dāng)前執(zhí)行指令的地址浸船,一旦該指令被執(zhí)行妄迁,pc寄存器會(huì)被更新至下條指令的地址找前。

2.5 本地方法棧

本地方法棧保存本地方法信息。對(duì)每一個(gè)線程判族,將創(chuàng)建一個(gè)單獨(dú)的本地方法棧躺盛。

3. 執(zhí)行引擎

分配給運(yùn)行時(shí)數(shù)據(jù)區(qū)的字節(jié)碼將由執(zhí)行引擎執(zhí)行。執(zhí)行引擎讀取字節(jié)碼并逐段執(zhí)行形帮。

3.1 解釋器:

解釋器能快速的解釋字節(jié)碼槽惫,但執(zhí)行卻很慢。 解釋器的缺點(diǎn)就是,當(dāng)一個(gè)方法被調(diào)用多次辩撑,每次都需要重新解釋界斜。

編譯器

JIT編譯器消除了解釋器的缺點(diǎn)。執(zhí)行引擎利用解釋器轉(zhuǎn)換字節(jié)碼合冀,但如果是重復(fù)的代碼則使用JIT編譯器將全部字節(jié)碼編譯成本機(jī)代碼各薇。本機(jī)代碼將直接用于重復(fù)的方法調(diào)用,這提高了系統(tǒng)的性能君躺。

a. 中間代碼生成器 – 生成中間代碼

b. 代碼優(yōu)化器 – 負(fù)責(zé)優(yōu)化上面生成的中間代碼

c. 目標(biāo)代碼生成器– 負(fù)責(zé)生成機(jī)器代碼或本機(jī)代碼

d. 探測(cè)器(Profiler) – 一個(gè)特殊的組件峭判,負(fù)責(zé)尋找被多次調(diào)用的方法。

3.3 垃圾回收器:

收集并刪除未引用的對(duì)象棕叫×煮Γ可以通過(guò)調(diào)用"System.gc()"來(lái)觸發(fā)垃圾回收,但并不保證會(huì)確實(shí)進(jìn)行垃圾回收俺泣。JVM的垃圾回收只收集哪些由new關(guān)鍵字創(chuàng)建的對(duì)象疗认。所以,如果不是用new創(chuàng)建的對(duì)象伏钠,你可以使用finalize函數(shù)來(lái)執(zhí)行清理横漏。

Java本地接口 (JNI): JNI 會(huì)與本地方法庫(kù)進(jìn)行交互并提供執(zhí)行引擎所需的本地庫(kù)。

本地方法庫(kù):它是一個(gè)執(zhí)行引擎所需的本地庫(kù)的集合熟掂。

JVM三大核心區(qū)域

通過(guò)一個(gè)小程序認(rèn)識(shí)JVM

package com.spark.jvm;
/** 
* 從JVM調(diào)用的角度分析java程序堆內(nèi)存空間的使用: 
* 當(dāng)JVM進(jìn)程啟動(dòng)的時(shí)候缎浇,會(huì)從類(lèi)加載路徑中找到包含main方法的入口類(lèi)HelloJVM 
* 找到HelloJVM會(huì)直接讀取該文件中的二進(jìn)制數(shù)據(jù),并且把該類(lèi)的信息放到運(yùn)行時(shí)的Method內(nèi)存區(qū)域中打掘。 
* 然后會(huì)定位到HelloJVM中的main方法的字節(jié)碼中华畏,并開(kāi)始執(zhí)行Main方法中的指令 * 此時(shí)會(huì)創(chuàng)建Student實(shí)例對(duì)象鹏秋,并且使用student來(lái)引用該對(duì)象(或者說(shuō)給該對(duì)象命名)尊蚁,其內(nèi)幕如下: 
* 第一步:JVM會(huì)直接到Method區(qū)域中去查找Student類(lèi)的信息,此時(shí)發(fā)現(xiàn)沒(méi)有Student類(lèi)侣夷,就通過(guò)類(lèi)加載器加載該Student類(lèi)文件横朋; 
* 第二步:在JVM的Method區(qū)域中加載并找到了Student類(lèi)之后會(huì)在Heap區(qū)域中為Student實(shí)例對(duì)象分配內(nèi)存, 
* 并且在Student的實(shí)例對(duì)象中持有指向方法區(qū)域中的Student類(lèi)的引用(內(nèi)存地址)百拓; 
* 第三步:JVM實(shí)例化完成后會(huì)在當(dāng)前線程中為Stack中的reference建立實(shí)際的應(yīng)用關(guān)系琴锭,此時(shí)會(huì)賦值給student 
* 接下來(lái)就是調(diào)用方法
* 在JVM中方法的調(diào)用一定是屬于線程的行為晰甚,也就是說(shuō)方法調(diào)用本身會(huì)發(fā)生在線程的方法調(diào)用棧: 
* 線程的方法調(diào)用棧(Method Stack Frames),每一個(gè)方法的調(diào)用就是方法調(diào)用棧中的一個(gè)Frame决帖, 
* 該Frame包含了方法的參數(shù)厕九,局部變量,臨時(shí)數(shù)據(jù)等 student.sayHello();
*/
public class HelloJVM { 
        //在JVM運(yùn)行的時(shí)候會(huì)通過(guò)反射的方式到Method區(qū)域找到入口方法main
        public static void main(String[] args) {//main方法也是放在Method方法區(qū)域中的        
        /**      
        * student(小寫(xiě)的)是放在主線程中的Stack區(qū)域中的      
        * Student對(duì)象實(shí)例是放在所有線程共享的Heap區(qū)域中的      
        */      
        Student student = new Student("spark");     
        /**     
         * 首先會(huì)通過(guò)student指針(或句柄)(指針就直接指向堆中的對(duì)象地回,句柄      表明有一個(gè)中間的,student指向句柄扁远,句柄指向?qū)ο螅?        
        * 找Student對(duì)象,當(dāng)找到該對(duì)象后會(huì)通過(guò)對(duì)象內(nèi)部指向方法區(qū)域中的指針來(lái)調(diào)用具體的方法去執(zhí)行任務(wù)       
        */      
        student.sayHello(); 
      }} 

class Student { 
  // name本身作為成員是放在stack區(qū)域的但是name指向的String對(duì)象是放在Heap中 
    private String name;    
    public Student(String name) {       
            this.name = name;   
    }   
    //sayHello這個(gè)方法是放在方法區(qū)中的  
    public void sayHello() {    
          System.out.println("Hello, this is " + this.name);    
    }
}

JVM三大性能調(diào)優(yōu)參數(shù):-Xms –Xmx –Xss

-Xms –Xmx是對(duì)堆的性能調(diào)優(yōu)參數(shù)刻像,一般兩個(gè)設(shè)置是一樣的畅买,如果不一樣,當(dāng)Heap不夠用细睡,會(huì)發(fā)生內(nèi)存抖動(dòng)谷羞。一般都調(diào)大這兩個(gè)參數(shù),并且兩個(gè)大小一樣溜徙。

-Xss是對(duì)每一個(gè)線程棧的性能調(diào)優(yōu)參數(shù),影響堆棧調(diào)用的深度

實(shí)戰(zhàn)演示從OOM推導(dǎo)出JVM GC時(shí)候基于的內(nèi)存結(jié)構(gòu):Young Generation(Eden湃缎、From、To)蠢壹、OldGeneration雁歌、Permanent Generation

JVMHeap區(qū)域(年輕代、老年代)和方法區(qū)(永久代)結(jié)構(gòu)圖:

從Java GC的角度解讀代碼:程序20行new的Person對(duì)象會(huì)首先會(huì)進(jìn)入年輕代的Eden中(如果對(duì)象太大可能直接進(jìn)入年老代)知残。在GC之前對(duì)象是存在Eden和from中的靠瞎,進(jìn)行GC的時(shí)候Eden中的對(duì)象被拷貝到To這樣一個(gè)survive空間(survive幸存)空間:包括from和to,他們的空間大小是一樣的求妹,又叫s1和s2)中(有一個(gè)拷貝算法)乏盐,F(xiàn)rom中的對(duì)象(算法會(huì)考慮經(jīng)過(guò)GC幸存的次數(shù))到一定次數(shù)(閾值(如果說(shuō)每次GC之后這個(gè)對(duì)象依舊在Survive中存在,GC一次他的Age就會(huì)加1制恍,默認(rèn)15就會(huì)放到OldGeneration父能。但是實(shí)際情況比較復(fù)雜,有可能沒(méi)有到閾值就從Survive區(qū)域直接到Old Generation區(qū)域净神。在進(jìn)行GC的時(shí)候會(huì)對(duì)Survive中的對(duì)象進(jìn)行判斷何吝,Survive空間中有一些對(duì)象Age是一樣的,也就是經(jīng)過(guò)的GC次數(shù)一樣鹃唯,年齡相同的這樣一批對(duì)象的總和大于等于Survive空間一半的話爱榕,這組對(duì)象就會(huì)進(jìn)入old Generation中,(是一種動(dòng)態(tài)的調(diào)整)))坡慌,會(huì)被復(fù)制到OldGeneration黔酥,如果沒(méi)到次數(shù)From中的對(duì)象會(huì)被復(fù)制到To中,復(fù)制完成后To中保存的是有效的對(duì)象,Eden和From中剩下的都是無(wú)效的對(duì)象跪者,這個(gè)時(shí)候就把Eden和From中所有的對(duì)象清空棵帽。在復(fù)制的時(shí)候Eden中的對(duì)象進(jìn)入To中,To可能已經(jīng)滿了渣玲,這個(gè)時(shí)候Eden中的對(duì)象就會(huì)被直接復(fù)制到Old Generation中逗概,F(xiàn)rom中的對(duì)象也會(huì)直接進(jìn)入Old Generation中。就是存在這樣一種情況忘衍,To比較小仗谆,第一次復(fù)制的時(shí)候空間就滿了,直接進(jìn)入old Generation中淑履。復(fù)制完成后隶垮,To和From的名字會(huì)對(duì)調(diào)一下,因?yàn)镋den和From都是空的秘噪,對(duì)調(diào)后Eden和To都是空的狸吞,下次分配就會(huì)分配到Eden。一直循環(huán)這個(gè)流程指煎。好處:使用對(duì)象最多和效率最高的就是在Young Generation中蹋偏,通過(guò)From to就避免過(guò)于頻繁的產(chǎn)生FullGC(Old Generation滿了一般都會(huì)產(chǎn)生FullGC)

虛擬機(jī)在進(jìn)行MinorGC(新生代的GC)的時(shí)候,會(huì)判斷要進(jìn)入OldGeneration區(qū)域?qū)ο蟮拇笮≈寥溃欠翊笥贠ld Generation剩余空間大小威始,如果大于就會(huì)發(fā)生Full GC。

剛分配對(duì)象在Eden中像街,如果空間不足嘗試進(jìn)行GC黎棠,回收空間,如果進(jìn)行了MinorGC空間依舊不夠就放入Old Generation镰绎,如果OldGeneration空間還不夠就OOM了脓斩。

比較大的對(duì)象,數(shù)組等畴栖,大于某值(可配置)就直接分配到老年代随静,(避免頻繁內(nèi)存拷貝)

年輕代和年老代屬于Heap空間的

Permanent Generation(永久代)可以理解成方法區(qū),(它屬于方法區(qū))也有可能發(fā)生GC吗讶,例如類(lèi)的實(shí)例對(duì)象全部被GC了燎猛,同時(shí)它的類(lèi)加載器也被GC掉了,這個(gè)時(shí)候就會(huì)觸發(fā)永久代中對(duì)象的GC照皆。

如果OldGeneration滿了就會(huì)產(chǎn)生FullGC

滿原因:
1重绷,from survive中對(duì)象的生命周期到一定閾值

2,分配的對(duì)象直接是大對(duì)象

3纵寝、由于To 空間不夠论寨,進(jìn)行GC直接把對(duì)象拷貝到年老代(年老代GC時(shí)候采用不同的算法)

如果Young Generation大小分配不合理或空間比較小,這個(gè)時(shí)候?qū)е聦?duì)象很容易進(jìn)入Old Generation中爽茴,而Old Generation中回收具體對(duì)象的時(shí)候速度是遠(yuǎn)遠(yuǎn)低于Young Generation回收速度葬凳。

因此實(shí)際分配要考慮年老代和新生代的比例,考慮Eden和survives的比例

Permanent Generation中發(fā)生GC的時(shí)候也對(duì)性能影響非常大室奏,也是Full GC

JVM GC時(shí)候核心參數(shù):

-XX:NewRatio –XX:SurvivorRatio –XX:NewSize –XX:MaxNewSize

–XX:NewSize–XX:MaxNewSize指定新生代初始大小和最大大小火焰。

1,-XX:NewRatio 是年老代 新生代相對(duì)的比例胧沫,比如NewRatio=2昌简,表明年老代是新生代的2倍。老年代占了heap的2/3绒怨,新生代占了1/3

2纯赎,-XX:SurvivorRatio 配置的是在新生代里面Eden和一個(gè)Servive的比例

如果指定NewRatio還可以指定NewSizeMaxNewSize,如果同時(shí)指定了會(huì)如何南蹂?犬金??

NewRatio=2六剥,這個(gè)時(shí)候新生代會(huì)嘗試分配整個(gè)Heap大小的1/3的大小晚顷,但是分配的空間不會(huì)小于-XX:NewSize也不會(huì)大于 –XX:MaxNewSize

3,-XX:NewSize –XX:MaxNewSize

實(shí)際設(shè)置比例還是設(shè)置固定大小疗疟,固定大小理論上速度更高该默。

-XX:NewSize –XX:MaxNewSize理論越大越好,但是整個(gè)Heap大小是有限的策彤,一般年輕代的設(shè)置大小不要超過(guò)年老代栓袖。

-XX:SurvivorRatio新生代里面Eden和一個(gè)Servive的比例,如果SurvivorRatio是5的話店诗,也就是Eden區(qū)域是SurviveTo區(qū)域的5倍叽赊。Survive由From和To構(gòu)成。結(jié)果就是整個(gè)Eden占用了新生代5/7必搞,F(xiàn)rom和To分別占用了1/7,如果分配不合理必指,Eden太大,這樣產(chǎn)生對(duì)象很順利恕洲,但是進(jìn)行GC有一部分對(duì)象幸存下來(lái)塔橡,拷貝到To,空間小霜第,就沒(méi)有足夠的空間葛家,對(duì)象會(huì)被放在old Generation中。如果Survive空間大泌类,會(huì)有足夠的空間容納GC后存活的對(duì)象癞谒,但是Eden區(qū)域小,會(huì)被很快消耗完,這就增加了GC的次數(shù)弹砚。

JVM的GC日志解讀:

一双仍、 JVM YoungGeneration下MinorGC日志詳解

[GC (Allocation Failure) [PSYoungGen:2336K->288K(2560K)] 8274K->6418K(9728K), 0.0112926 secs] [Times:user=0.06 sys=0.00, real=0.01 secs]

PSYoungGen(是新生代類(lèi)型,新生代日志收集器)桌吃,2336K表示使用新生代GC前朱沃,占用的內(nèi)存,->288K表示GC后占用的內(nèi)存茅诱,(2560K)代表整個(gè)新生代總共大小

8274K(GC前整個(gè)JVM Heap對(duì)內(nèi)存的占用)->6418K(MinorGC后內(nèi)存占用總量)(9728K)(整個(gè)堆的大卸何铩)0.0112926 secs(Minor GC消耗的時(shí)間)] [Times: user=0.06 sys=0.00, real=0.01 secs] 用戶空間,內(nèi)核空間時(shí)間的消耗瑟俭,real整個(gè)的消耗

二翎卓、 JVM的GC日志Full GC日志每個(gè)字段徹底詳解

[Full GC (Ergonomics) [PSYoungGen: 984K->425K(2048K)] [ParOldGen:7129K->7129K(7168K)] 8114K->7555K(9216K), [Metaspace:2613K->2613K(1056768K)], 0.1022588 secs] [Times: user=0.56 sys=0.02,real=0.10 secs]

[Full GC (Allocation Failure) [PSYoungGen: 425K->425K(2048K)][ParOldGen: 7129K->7129K(7168K)] 7555K->7555K(9216K), [Metaspace:2613K->2613K(1056768K)], 0.1003696 secs] [Times: user=0.64 sys=0.03,real=0.10 secs]

[Full GC(表明是Full GC) (Ergonomics) [PSYoungGen:FullGC會(huì)導(dǎo)致新生代Minor GC產(chǎn)生]984K->425K(2048K)][ParOldGen:(老年代GC)7129K(GC前多大)->7129K(GC后,并沒(méi)有降低內(nèi)存占用摆寄,因?yàn)閷?xiě)的程序不斷循環(huán)一直有引用)(7168K) (老年代總?cè)萘浚?strong>] 8114K(GC前占用整個(gè)Heap空間大辛觥)->7555K (GC后占用整個(gè)Heap空間大小) (9216K) (整個(gè)Heap大小椭迎,JVM堆的大腥裰摹), [Metaspace: (java6 7是permanentspace,java8改成Metaspace畜号,類(lèi)相關(guān)的一些信息) 2613K->2613K(1056768K) (GC前后基本沒(méi)變缴阎,空間很大)], 0.1022588 secs(GC的耗時(shí),秒為單位)] [Times: user=0.56 sys=0.02, real=0.10 secs](用戶空間耗時(shí)简软,內(nèi)核空間耗時(shí)蛮拔,真正的耗時(shí)時(shí)間)

三、 Java8中的JVM的MetaSpace

Metaspace的使用C語(yǔ)言實(shí)現(xiàn)的痹升,使用的是OS的空間建炫,Native Memory Space可動(dòng)態(tài)的伸縮,可以根據(jù)類(lèi)加載的信息的情況疼蛾,在進(jìn)行GC的時(shí)候進(jìn)行調(diào)整自身的大小肛跌,來(lái)延緩下一次GC的到來(lái)。

可以設(shè)置Metaspace的大小察郁,如果超過(guò)最大大小就會(huì)OOM衍慎,不設(shè)置如果把整個(gè)操作系統(tǒng)的內(nèi)存耗盡了出現(xiàn)OOM,一般會(huì)設(shè)置一個(gè)足夠大的初始值皮钠,安全其間會(huì)設(shè)置最大值稳捆。

永久代發(fā)生GC有兩種情況,類(lèi)的所有的實(shí)例被GC掉麦轰,且class load不存乔夯。

對(duì)于元數(shù)據(jù)空間 簡(jiǎn)化了GC砖织, class load不存在了就需要進(jìn)行GC。

三種基本的GC算法基石

一末荐、 標(biāo)記/清除算法

內(nèi)存中的對(duì)象構(gòu)成一棵樹(shù)侧纯,當(dāng)有效的內(nèi)存被耗盡的時(shí)候,程序就會(huì)停止鞠评,做兩件事茂蚓,第一:標(biāo)記壕鹉,標(biāo)記從樹(shù)根可達(dá)的對(duì)象(途中水紅色)剃幌,第二:清除(清楚不可達(dá)的對(duì)象)。標(biāo)記清除的時(shí)候有停止程序運(yùn)行晾浴,如果不停止负乡,此時(shí)如果存在新產(chǎn)生的對(duì)象,這個(gè)對(duì)象是樹(shù)根可達(dá)的脊凰,但是沒(méi)有被標(biāo)記(標(biāo)記已經(jīng)完成了)抖棘,會(huì)清除掉。

缺點(diǎn):遞歸效率低性能低狸涌;釋放空間不連續(xù)容易導(dǎo)致內(nèi)存碎片切省;會(huì)停止整個(gè)程序運(yùn)行;


二帕胆、 復(fù)制算法

把內(nèi)存分成兩塊區(qū)域:空閑區(qū)域和活動(dòng)區(qū)域朝捆,第一還是標(biāo)記(標(biāo)記誰(shuí)是可達(dá)的對(duì)象),標(biāo)記之后把可達(dá)的對(duì)象復(fù)制到空閑區(qū)懒豹,將空閑區(qū)變成活動(dòng)區(qū)芙盘,同時(shí)把以前活動(dòng)區(qū)對(duì)象1,4清除掉脸秽,變成空閑區(qū)儒老。

速度快但耗費(fèi)空間,假定活動(dòng)區(qū)域全部是活動(dòng)對(duì)象记餐,這個(gè)時(shí)候進(jìn)行交換的時(shí)候就相當(dāng)于多占用了一倍空間驮樊,但是沒(méi)啥用。

三片酝、 標(biāo)記整理算法

平衡點(diǎn)

標(biāo)記誰(shuí)是活躍對(duì)象巩剖,整理,會(huì)把內(nèi)存對(duì)象整理成一課樹(shù)一個(gè)連續(xù)的空間钠怯,

JVM垃圾回收分代收集算法

綜合了上述算法優(yōu)略

1佳魔, 分代GC在新生代的算法:采用了GC的復(fù)制算法,速度快晦炊,因?yàn)樾律话闶切聦?duì)象鞠鲜,都是瞬態(tài)的用了可能很快被釋放的對(duì)象宁脊。

2, 分代GC在年老代的算法 標(biāo)記/整理算法贤姆,GC后會(huì)執(zhí)行壓縮榆苞,整理到一個(gè)連續(xù)的空間,這樣就維護(hù)著下一次分配對(duì)象的指針霞捡,下一次對(duì)象分配就可以采用碰撞指針技術(shù)坐漏,將新對(duì)象分配在第一個(gè)空閑的區(qū)域。

JVM垃圾回收器串行碧信、并行赊琳、并發(fā)垃圾回收器概述

1, JVM中不同的垃圾回收器

2砰碴, 串行躏筏,并行,并發(fā)垃圾回收器(和JVM歷史有關(guān)系呈枉,剛開(kāi)始串行)

Java中Stop-The-World機(jī)制簡(jiǎn)稱(chēng)STW趁尼,是在執(zhí)行垃圾收集算法時(shí),Java應(yīng)用程序的其他所有線程都被掛起(除了垃圾收集幫助器之外)猖辫。Java中一種全局暫退峙ⅲ現(xiàn)象,全局停頓啃憎,所有Java代碼停止芝囤,native代碼可以執(zhí)行,但不能與JVM交互荧飞;這些現(xiàn)象多半是由于gc引起凡人。

JVM中Serial收集器、ParNew收集器叹阔、Parallel收集器解析

Serial收集器 單線程方式(沒(méi)有線程切換開(kāi)銷(xiāo)挠轴,如果受限物理機(jī)器單線程可采用)串行且采用stop the world在工作的時(shí)候程序會(huì)停止

Serial和serial old

ParNew收集器:多線程(多CPU和多Core的環(huán)境中高效),生產(chǎn)環(huán)境對(duì)低延時(shí)要求高的話耳幢,就采用ParNew和CMS組合來(lái)進(jìn)行server端的垃圾回收

Parallel 收集器:多線程岸晦,并行, 它可以控制JVM吞吐量的大小睛藻,吞吐量?jī)?yōu)先的收集器启上,一般設(shè)置1%,可設(shè)置程序暫停的時(shí)間店印,會(huì)通過(guò)把新生代空間變小冈在,來(lái)完成回收,頻繁的小規(guī)模垃圾回收按摘,會(huì)影響程序吞吐量大小

JVM中CMS收集器解密

低延遲進(jìn)行垃圾回收包券,在線服務(wù)和處理速度要求高的情況下很重要

配置:XX:UseConcMarkSweepGC

concurrence(并發(fā)) Mark(標(biāo)記)Sweep(清理)

低延時(shí)

把垃圾回收分成四個(gè)階段

CMS-initial-mark初始標(biāo)記階段會(huì)stop the world纫谅,短暫的暫停程序根據(jù)跟對(duì)象標(biāo)記的對(duì)象所連接的對(duì)象是否可達(dá)來(lái)標(biāo)記出哪些可到達(dá)

CMS-concurrent-mark并發(fā)標(biāo)記,根據(jù)上一次標(biāo)記的結(jié)果確定哪些不可到達(dá)溅固,線程并發(fā)或交替之行付秕,基本不會(huì)出現(xiàn)程序暫停。

CMS-remark再次標(biāo)記侍郭,會(huì)出現(xiàn)程序暫停询吴,所有內(nèi)存那一時(shí)刻靜止,確保被全部標(biāo)記亮元,有可能第二階段之前有可能被標(biāo)記為垃圾的對(duì)象有可能被引用猛计,在此標(biāo)記確認(rèn)。

CMS-concurrent-sweep并發(fā)清理垃圾苹粟,把標(biāo)記的垃圾清理掉了有滑,沒(méi)有壓縮跃闹,有可能產(chǎn)生內(nèi)存碎片嵌削,不連續(xù)的內(nèi)存塊,這時(shí)候就不能更好的使用內(nèi)存望艺,可以通過(guò)一個(gè)參數(shù)配置苛秕,根據(jù)內(nèi)存的情況執(zhí)行壓縮。

JVM中G1收集器

可以像CMS收集器一樣找默,GC操作與應(yīng)用的現(xiàn)場(chǎng)一起并發(fā)執(zhí)行

緊湊的空閑內(nèi)存區(qū)域且沒(méi)有很長(zhǎng)的GC停頓時(shí)間

需要可預(yù)測(cè)的GC暫停耗時(shí)

不想犧牲太多吞吐量性能

啟動(dòng)后不需要請(qǐng)求更大的Java堆

通過(guò)案例瞬間理解JVM中PSYoungGen艇劫、ParOldGen、MetaSpace

Heap PSYoungGen      total 2560K, used 321K[0x00000007bfd00000, 0x00000007c0000000, 0x00000007c0000000)  eden space 2048K, 15% used[0x00000007bfd00000,0x00000007bfd50568,0x00000007bff00000)  from space 512K, 0% used[0x00000007bff00000,0x00000007bff00000,0x00000007bff80000)  to   space 512K, 0% used[0x00000007bff80000,0x00000007bff80000,0x00000007c0000000) ParOldGen       total 7168K, used 7097K[0x00000007bf600000, 0x00000007bfd00000, 0x00000007bfd00000) object space 7168K, 99%used [0x00000007bf600000,0x00000007bfcee7b8,0x00000007bfd00000) Metaspace       used 2647K, capacity 4486K, committed4864K, reserved 1056768K class space    used 289K, capacity 386K, committed 512K,reserved 1048576K

PSYoungGen是eden + from

使用MAT對(duì)Dump文件進(jìn)行分析實(shí)戰(zhàn)

導(dǎo)出Dump文件

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末惩激,一起剝皮案震驚了整個(gè)濱河市店煞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌风钻,老刑警劉巖顷蟀,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異骡技,居然都是意外死亡鸣个,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)布朦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)囤萤,“玉大人,你說(shuō)我怎么就攤上這事是趴√紊幔” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵唆途,是天一觀的道長(zhǎng)富雅。 經(jīng)常有香客問(wèn)我缤削,道長(zhǎng),這世上最難降的妖魔是什么吹榴? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任亭敢,我火速辦了婚禮,結(jié)果婚禮上图筹,老公的妹妹穿的比我還像新娘帅刀。我一直安慰自己,他們只是感情好远剩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布扣溺。 她就那樣靜靜地躺著,像睡著了一般瓜晤。 火紅的嫁衣襯著肌膚如雪锥余。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,155評(píng)論 1 299
  • 那天痢掠,我揣著相機(jī)與錄音驱犹,去河邊找鬼。 笑死足画,一個(gè)胖子當(dāng)著我的面吹牛雄驹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播淹辞,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼医舆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了象缀?” 一聲冷哼從身側(cè)響起蔬将,我...
    開(kāi)封第一講書(shū)人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎央星,沒(méi)想到半個(gè)月后霞怀,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡等曼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年里烦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片禁谦。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡胁黑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出州泊,到底是詐尸還是另有隱情丧蘸,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站力喷,受9級(jí)特大地震影響刽漂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜弟孟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一贝咙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拂募,春花似錦庭猩、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至录肯,卻和暖如春趴腋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背论咏。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工优炬, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人潘靖。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓穿剖,卻偏偏與公主長(zhǎng)得像蚤蔓,于是被迫代替她去往敵國(guó)和親卦溢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

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

  • 1.什么是垃圾回收秀又? 垃圾回收(Garbage Collection)是Java虛擬機(jī)(JVM)垃圾回收器提供...
    簡(jiǎn)欲明心閱讀 89,484評(píng)論 17 311
  • jvm原理 Java虛擬機(jī)是整個(gè)java平臺(tái)的基石吐辙,是java技術(shù)實(shí)現(xiàn)硬件無(wú)關(guān)和操作系統(tǒng)無(wú)關(guān)的關(guān)鍵環(huán)節(jié)宣决,是java...
    AI喬治閱讀 17,242評(píng)論 21 486
  • 作者:一字馬胡 轉(zhuǎn)載標(biāo)志 【2017-11-12】 更新日志 日期更新內(nèi)容備注 2017-11-12新建文章初版 ...
    beneke閱讀 2,202評(píng)論 0 7
  • 原文閱讀 前言 這段時(shí)間懈怠了,罪過(guò)昏苏! 最近看到有同事也開(kāi)始用上了微信公眾號(hào)寫(xiě)博客了尊沸,挺好的~給他們點(diǎn)贊,這博客我...
    碼農(nóng)戲碼閱讀 5,961評(píng)論 2 31
  • 星期六早上贤惯,媽媽給我布置了兩篇作文洼专,說(shuō)是下班回來(lái)檢查,我爽快地答應(yīng)了孵构。我看了看時(shí)間還早屁商,就想先看一會(huì)兒電視吧...
    有為齋閱讀 227評(píng)論 0 0