Java虛擬機(jī):垃圾收集機(jī)制

版權(quán)聲明:本文為斑馬君學(xué)習(xí)總結(jié)文章饱须,轉(zhuǎn)載請注明出處瑟由!

一、垃圾回收

上篇博客介紹了Java內(nèi)存運(yùn)行時區(qū)域的各個部分,其中程序計數(shù)器歹苦、虛擬機(jī)棧、本地方法棧三個區(qū)域隨線程而生督怜,隨線程而滅殴瘦;棧中的棧幀隨著方法的進(jìn)入和退出而有條不不紊地執(zhí)行著出棧和入棧操作。每一個棧幀中分配多少內(nèi)存基本上是在類結(jié)構(gòu)確定下來時就已知的号杠。)蚪腋,因此這幾個區(qū)域的內(nèi)存分配和回收都具備確定性,在這幾個區(qū)域內(nèi)就不需要過多考慮回收的問題姨蟋,因為方法結(jié)束或者線程結(jié)束時屉凯,內(nèi)存自然就跟隨著回收了。

Java堆和方法區(qū)則不一樣眼溶,一個接口中的多個實現(xiàn)類需要的內(nèi)存可能不一樣悠砚,一個方法中的多個分支需要的內(nèi)存也可能不一樣,我們只有在程序處于運(yùn)行期間時才能知道會創(chuàng)建哪些對象堂飞,這部分內(nèi)存的分配和回收都是動態(tài)的灌旧,垃圾收集器所關(guān)注的是這部分內(nèi)存。
GC需要完成的3件事情:

  • 如何判定對象為垃圾對象
  • 如何回收
  • 何時回收
二绰筛、如何判定對象為垃圾對象

在堆里面存放著Java世界中幾乎所有的對象實例枢泰,垃圾收集器在對堆進(jìn)行回收前,第一件事情就是要確定這些對象之中哪些還“存活”著铝噩,哪些已經(jīng)“死去”衡蚂。

引用計數(shù)算法

在對象中添加一個引用計數(shù)器,當(dāng)有地方引用這個對象的時候骏庸,引用計數(shù)器的值就+1,當(dāng)引用失效的時候毛甲,計數(shù)器的值就-1.該算法缺陷是難解決對象之間相互循環(huán)引用的問題。
public class Main {

private Object instance;

public Main() {
    byte[] m = new byte[20 * 1024 *1024];
}

public static void main(String[] args) {
    
    Main m1 = new Main();
    
    Main m2 = new Main();
    
    m1.instance = m2;
    m2.instance = m1;
    
    m1 = null;
    m2 = null;
    
    System.gc();
}

VM arguments參數(shù)設(shè)置:-verbose:gc -XX:+PrintGCDetails

從運(yùn)行結(jié)果中可以清楚看到敞恋,GC日志中包含“707K->476K”丽啡,意味著虛擬機(jī)并沒有因為這兩個對象互相引用就不回收它們,這也從側(cè)面說明虛擬機(jī)并不是通過引用計數(shù)算法來判斷對象是否存活的硬猫。

可達(dá)性分析算法

這個算法的基本思路就是通過一些列的稱為"GC Roots"的對象作為起始點(diǎn)补箍,從這些節(jié)點(diǎn)開始向下搜索,搜索所走過的路徑稱為引用鏈啸蜜,當(dāng)一個對象到GC Roots沒有任何引用鏈相連時坑雅,則證明此對象是不可用的。

在java語言中衬横,可作為GC Roots的對象包括下面幾種:

  • 虛擬機(jī)棧(棧幀中的本地變量表)中引用的對象
  • 方法區(qū)中類靜態(tài)屬性引用的對象
  • 方法區(qū)中常量引用的對象
  • 本地方法棧中JNI引用的對象

再談引用

無論是通過引用計數(shù)算法判斷對象的引用數(shù)量裹粤,還是通過可達(dá)性分析算法判斷對象的引用鏈?zhǔn)欠窨蛇_(dá),判定對象是否存活都與“引用”有關(guān)蜂林。希望能描述這樣一類對象:當(dāng)內(nèi)存空間還足夠時遥诉,則能保留在內(nèi)存之中拇泣;如果內(nèi)存空間在進(jìn)行垃圾收集后還是非常緊張,則可以拋棄這些對象矮锈。很多系統(tǒng)的緩存功能都符合這樣的應(yīng)用場景霉翔。

在JDK 1.2之后,Java對引用的概念進(jìn)行了擴(kuò)充苞笨,將引用分為強(qiáng)引用(Strong
Reference)债朵、軟引用(Soft Reference)、弱引用(Weak Reference)瀑凝、虛引用(PhantomReference)4種序芦,這4種引用強(qiáng)度依次逐漸減弱。

  • 強(qiáng)引用就是指在程序代碼之中普遍存在的粤咪,類似“Object obj=new Object()”這類的引用谚中,只要強(qiáng)引用還存在,垃圾收集器永遠(yuǎn)不會回收掉被引用的對象射窒。
  • 軟引用是用來描述一些還有用但并非必需的對象藏杖。對于軟引用關(guān)聯(lián)著的對象,在系統(tǒng)將要發(fā)生內(nèi)存溢出異常之前脉顿,將會把這些對象列進(jìn)回收范圍之中進(jìn)行第二次回收蝌麸。如果這次回收還沒有足夠的內(nèi)存,才會拋出內(nèi)存溢出異常艾疟。在JDK 1.2之后来吩,提供了SoftReference類來實現(xiàn)軟引用。
  • 弱引用也是用來描述非必需對象的蔽莱,但是它的強(qiáng)度比軟引用更弱一些弟疆,被弱引用關(guān)聯(lián)的對象只能生存到下一次垃圾收集發(fā)生之前。當(dāng)垃圾收集器工作時盗冷,無論當(dāng)前內(nèi)存是否足夠怠苔,都會回收掉只被弱引用關(guān)聯(lián)的對象。在JDK 1.2之后仪糖,提供了WeakReference類來實現(xiàn)弱引用柑司。
三、如何回收

回收策略:標(biāo)記-清除算法

算法分為”標(biāo)記“和”清除“兩個階段:首先標(biāo)記出所有需要回收的對象锅劝,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對象攒驰。

該算法主要有兩個不足的問題:

效率問題:標(biāo)記和清除兩個過程的效率都不高;
空間問題:標(biāo)記清除之后會產(chǎn)生大量不連續(xù)的內(nèi)存碎片故爵,空間碎片太多可能會導(dǎo)致以后在程序運(yùn)行過程中需要分配較大對象時玻粪,無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動作。

回收策略:復(fù)制算法

該算法將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊劲室。當(dāng)這一塊的內(nèi)存用完了伦仍,就將還存活著的對象復(fù)制到另外一塊上面,然后再把已使用過的內(nèi)存空間一次清理掉痹籍。

活著的對象復(fù)制到另外一塊上面
已使用過的內(nèi)存空間一次清理掉
現(xiàn)在的商業(yè)虛擬機(jī)都采用這種收集算法來回收新生代呢铆,IBM公司的專門研究表明,新生代中的對象98%是“朝生死”的蹲缠,所以并不需要按照1:1的比例來劃分內(nèi)存空間,而是將內(nèi)存分為一塊較大的Eden空間和兩塊較小的Survivor空間悠垛,每次使用Eden和其中一塊Survivor线定。當(dāng)回收時,將Eden和Survivor中還存活著的對象一次性地復(fù)制到另外一塊Survivor空間上确买,最后清理掉Eden和剛才用過的Survivor空間斤讥。

當(dāng)回收時,將Eden和Survivor中還存活著的對象一次性地復(fù)制到另外一塊Survivor空間上湾趾,最后清理掉Eden和剛才用過的Survivor空間芭商。

回收策略:標(biāo)記-整理算法和分代收集算法

復(fù)制收集算法在對象存活率較高時就要進(jìn)行較多的復(fù)制操作,效率將會變低搀缠。更關(guān)鍵的是铛楣,如果不想浪費(fèi)50%的空間,就需要有額外的空間進(jìn)行分配擔(dān)保艺普,以應(yīng)對被使用的內(nèi)存中所有對象都100%存活的極端情況簸州,所以在老年代一般不能直接選用這種算法。

“標(biāo)記-清除”算法:不是直接對可回收對象進(jìn)行清理歧譬,而是讓所有存活的對象都向一端移動岸浑,然后直接清理掉端邊界以外的內(nèi)存。

標(biāo)記-整理算法
“分代收集算法:根據(jù)對象存活周期的不同將內(nèi)存劃分為幾塊瑰步。一般是把Java堆分為新生代和老年代矢洲,這樣就可以根據(jù)各個年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴ā?strong>在新生代中,每次垃圾收集時都發(fā)現(xiàn)有大批對象死去缩焦,只有少量存活读虏,那就選用復(fù)制算法,只需要付出少量存活對象的復(fù)制成本就可以完成收集舌界。而老年代中因為對象存活率高掘譬、沒有額外空間。對它進(jìn)行分配擔(dān)保呻拌,就必須使用“標(biāo)記—清理”或者“標(biāo)記—整理”算法來進(jìn)行回收葱轩。

四、垃圾收集器

新生代收集器-Serial收集器

是最基本、發(fā)展歷史最悠久的收集器靴拱。曾經(jīng)(在JDK 1.3.1之前)是虛擬機(jī)新生代收集的唯一選擇垃喊。這個收集器是一個單線程的收集器,但它的“單線程”的意義并不僅僅說明它只會使用一個CPU或一條收集線程去完成垃圾收集工作袜炕,更重要的是在它進(jìn)行垃圾收集時本谜,必須暫停其他所有的工作線程,直到它收集結(jié)束偎窘。

Serial收集器由于沒有線程交互的開銷乌助,專心做垃圾收集自然可以獲得最高的單線程收集效率。陌知,收集幾十兆甚至一兩百兆的新生代他托,停頓時間完全可以控制在幾十毫秒最多一百多毫秒以內(nèi),只要不是頻繁發(fā)生仆葡,這點(diǎn)停頓是可以接受的赏参。

Serial收集器可用的所有控制參數(shù)(例如:-XX:SurvivorRatio、-XX:PretenureSizeThreshold沿盅、-XX:HandlePromotionFailure等)

新生代收集器-ParNew收集器

ParNew收集器其實就是Serial收集器的多線程版本把篓,除了使用多條線程進(jìn)行垃圾收集外,其余與Serial收集器完全一樣腰涧。ParNew收集器是許多運(yùn)行在Server模式下的虛擬機(jī)中首選的新生代收集器韧掩。

ParNew收集器在單CPU的環(huán)境中絕對不會有比Serial收集器更好的效果,甚至由于存在線程交互的開銷南窗,該收集器在通過超線程技術(shù)實現(xiàn)的兩個CPU的環(huán)境中都不能百分之百地保證可以超越Serial收集器揍很。當(dāng)然,隨著可以使用的CPU的數(shù)量的增加万伤,它對于GC時系統(tǒng)資源的有效利用還是很有好處的窒悔。

使用-XX:ParallelGCThreads參數(shù)來限制垃圾收集的線程數(shù)。使用-XX:+UseConcMarkSweepGC選項后的默認(rèn)新生代收集器敌买,也可以使用-XX:+UseParNewGC選項來強(qiáng)制指定它简珠。

新生代收集器-Parallel Scavenge收集器

Parallel Scavenge收集器是一個新生代收集器,使用復(fù)制算法的并行收集器虹钮,Parallel Scavenge 收集器使用兩個參數(shù)控制吞吐量聋庵。
直觀上,只要最大的垃圾收集停頓時間越小芙粱,吞吐量是越高的祭玉,但是GC停頓時間的縮短是以犧牲吞吐量和新生代空間作為代價的。比如原來10秒收集一次春畔,每次停頓100毫秒脱货。但是線程編程每5秒收集一次岛都,每次停頓70毫秒,停頓時間下降的同時振峻,吞吐量也下降了臼疫。

停頓時間越短就越適合需要與用戶交互的程序,良好的響應(yīng)速度能提升用戶體驗扣孟,而高吞吐量則可以高效地利用CPU時間烫堤,盡快完成程序的運(yùn)算任務(wù),主要適合在后臺運(yùn)算而不需要太多交互的任務(wù)凤价。

Parallel Scavenge收集器提供了兩個參數(shù)用于精確控制吞吐量鸽斟,分別是控制最大垃圾收集停頓時間的-XX:MaxGCPauseMillis參數(shù)以及直接設(shè)置吞吐量大小的-XX:GCTimeRatio參數(shù)。收集器有一個參數(shù)- XX:+UseAdaptiveSizePolicy當(dāng)這個參數(shù)打開之后利诺,就不需要手動指定新生代的大小湾盗,Eden和Survivor區(qū)的比例,晉升老年代對象等細(xì)節(jié)參數(shù)了立轧,虛擬機(jī)會根據(jù)當(dāng)前系統(tǒng)的運(yùn)行情況收集性能監(jiān)控信息,動態(tài)調(diào)整這些參數(shù)以提供最合適的停頓時間或者最大吞吐量躏吊,這種調(diào)節(jié)方式成為GC自適應(yīng)的調(diào)節(jié)策略氛改。

老年代收集器 - CMS收集器

由于垃圾回收時,都需要暫停用戶線程比伏,CMS(Concurrent Mark Sweep)收集器是一種以 獲取最短停頓時間 為目標(biāo)的收集器胜卤,重視服務(wù)的響應(yīng)速度,希望系統(tǒng)停頓時間最短赁项,能給用戶帶來良好的體驗葛躏。
CMS收集器是基于"標(biāo)記-清除"算法實現(xiàn)的,它的運(yùn)作過程比較復(fù)雜悠菜,整個過程分為四個步驟:

  • 初始標(biāo)記 初始標(biāo)記僅僅只是標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對象舰攒,速度很快,需要Stop The World(暫停所有的用戶線程)
  • 并發(fā)標(biāo)記 并發(fā)標(biāo)記階段就是進(jìn)行GC Roots Tracing的過程 (用戶不暫停)—用戶不暫停就還可能產(chǎn)生一些對象與GC Roots不可達(dá)
  • 重新標(biāo)記重新標(biāo)記階段是為了修正 并發(fā)標(biāo)記期間 因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動 的那一部分對象的標(biāo)記記錄悔醋,這個階段的停頓時間會比初始階段稍長一些,但是遠(yuǎn)比并發(fā)標(biāo)記的時間短摩窃,仍然需要"Stop The World"
  • 并發(fā)清除并發(fā)清除階段會清除對象(用戶不暫停)

整個過程中耗時最長的并發(fā)表及和并發(fā)清除過程收集線程可以與用戶線程一起工作,所以整體上來說芬骄,CMS收集器的內(nèi)存回收過程與用戶線程一起并發(fā)執(zhí)行猾愿。

優(yōu)點(diǎn):CMS是一款優(yōu)秀的收集器,主要優(yōu)點(diǎn):并發(fā)账阻、低停頓蒂秘。

缺點(diǎn):

  • CMS收集器對CPU的資源非常敏感,在并發(fā)階段淘太,它雖然不會導(dǎo)致用戶線程停頓姻僧,但是會因為占了一部分CPU資源规丽,而導(dǎo)致應(yīng)用程序變慢,總吞吐量會降低段化。
  • CMS無法處理浮動垃圾嘁捷,由于CMS 并發(fā)清理階段用戶線程還在運(yùn)行著,用戶線程在運(yùn)行自然就還會有新的垃圾產(chǎn)生显熏,CMS無法在當(dāng)次收集中處理掉它們雄嚣,只好留到下一次GC再清理掉,這一部分垃圾叫做"浮動垃圾"喘蟆。
  • CMS收集器會產(chǎn)生大量的空間碎片缓升,CMS是一款基于"標(biāo)記-清除" 算法實現(xiàn)的收集器,這意味著收集結(jié)束時會有大量空間碎片產(chǎn)生蕴轨「垡辏空間碎片過多時,就會給大對象的分配帶來很多麻煩橙弱,往往會出現(xiàn)還有很大的空間剩余歧寺,但是無法找到足夠大連續(xù)的空間來分配當(dāng)前對象,不得不提前觸發(fā)一次Full GC棘脐。

全區(qū)域的垃圾回收器 - G1收集器
G1垃圾回收器是用在heap memory很大的情況下斜筐,把heap劃分為很多很多的region塊,然后并行的對其進(jìn)行垃圾回收蛀缝。
G1垃圾回收器在清除實例所占用的內(nèi)存后顷链,還會做內(nèi)存壓縮。
G1垃圾回收器回收region的時候基本不會Stop The World屈梁,從整體來看是基于標(biāo)記-整理算法嗤练,從局部(兩個region之間)來看基于復(fù)制算法。

一個region有可能屬于Eden在讶、Survivor或者Tenured內(nèi)存煞抬,圖中的E表示Eden區(qū),S表示Survivor區(qū)真朗、T表示Tenured區(qū)此疹、空白就是未使用的空間。G1垃圾收集器還增加了一種新的內(nèi)存區(qū)域遮婶,叫做Humongous內(nèi)存區(qū)域蝗碎,如圖中的H塊。這種內(nèi)存區(qū)域主要用于存儲大對象-即大小超出一個region大小的50%的對象旗扑。
年輕代垃圾收集
在G1垃圾收集器中蹦骑,年輕代的垃圾回收過程使用復(fù)制算法,把Eden區(qū)和Survivor區(qū)的對象復(fù)制到新的Survivor區(qū)域臀防。
老年代垃圾收集
對于老年代的垃圾收集眠菇,G1(Garbage First)也分為四個階段边败,基本與CMS垃圾收集器一樣,但是略有不同捎废。

  • 初始標(biāo)記(Initial Mark) 同CMS垃圾收集器初始標(biāo)記階段一樣笑窜,G1也需要暫停應(yīng)用程序的執(zhí)行,它會標(biāo)記從跟對象出發(fā)登疗,在根對象的第一層孩子結(jié)點(diǎn)中標(biāo)記所有可達(dá)對象排截。但是G1的垃圾收集器的初始標(biāo)記結(jié)點(diǎn)是跟Minor gc一起發(fā)生的。也就是說辐益,在G1中断傲,不用像CMS那樣,單獨(dú)暫停應(yīng)用程序的執(zhí)行來運(yùn)行初始標(biāo)記階段智政,而是在G1出發(fā)Minor gc的時候一并將老年代上的初始標(biāo)記給做了认罩。
  • 并發(fā)標(biāo)記(Concurrent Mark) 同CMS垃圾收集器并發(fā)標(biāo)記階段一樣,但G1還多做了一件事件续捂,就是如果在并發(fā)標(biāo)記階段垦垂,發(fā)現(xiàn)哪些Tenured region中對象的存活率很小或者基本沒有對象存活,那么G1就會在這個階段將其回收掉牙瓢,而不用等到后面的清除階段乔外,這也是Garbage First名字的由來,同時在該階段一罩,G1會計算每個region的存活率,方便后面的清除階段使用撇簿。
  • 最終標(biāo)記(CMS中的remark階段) 同CMS垃圾收集器重新標(biāo)記階段一樣聂渊,但是采用的算法不一樣,G1采用了一種叫做STAB(snapshot-at-the-begining)的算法能夠在Remark階段更快的標(biāo)記可達(dá)對象四瘫。
  • 篩選回收(clean up/Copy) 在G1中汉嗽,沒有CMS對于的Sweep階段。相反找蜜,它有一個Clean up/Copy階段饼暑,在這個階段中,G1會挑選出那么對象存活率低的region進(jìn)行回收洗做,這個階段也是和minor gc一同完成的弓叛。

    G1是一款面向服務(wù)端應(yīng)用的垃圾收集器,Hotspot開發(fā)團(tuán)隊賦予它的使命是未來可以替換掉JDK1.5中發(fā)布的CMS收集器
    你想追求低停頓诚纸、想讓用戶有更好的體驗用G1
    如果你的應(yīng)用追求吞吐量撰筷,G1并不能帶來很明顯的好處。

吞吐量

吞吐量就是CPU 運(yùn)行用戶代碼的時間 與 CPU總消耗時間 的比值畦徘。

吞吐量 = 運(yùn)行用戶代碼的時間 / (運(yùn)行用戶代碼的時間+垃圾收集的時間)

假設(shè)虛擬機(jī)總共運(yùn)行了100分鐘毕籽,其中垃圾收集花了一分鐘 吞吐量就是99%抬闯,虛擬機(jī)總共運(yùn)行了100分鐘,其中垃圾收集花掉1分鐘关筒,那吞吐量就是99%溶握。停頓時間越短就越適合需要與用戶交互的程序牛柒,良好的響應(yīng)速度能提升用戶體驗俏橘,而高吞吐量則可以高效率地利用CPU時間,盡快完成程序的運(yùn)算任務(wù)菜职。

五廉赔、理解GC日志

閱讀GC日志是處理Java虛擬機(jī)內(nèi)存問題的基礎(chǔ)技能肉微,它只是一些人為確定的規(guī)則,沒有太多技術(shù)含量蜡塌。

最前面的數(shù)字“33.125:”和“100.667:”代表了GC發(fā)生的時間碉纳,這個數(shù)字的含義是從Java
虛擬機(jī)啟動以來經(jīng)過的秒數(shù)。

GC日志開頭的“[GC”和“[Full GC”說明了這次垃圾收集的停頓類型馏艾,而不是用來區(qū)分新生代GC還是老年代GC的劳曹。如果有“Full”,說明這次GC是發(fā)生了Stop-The-World的琅摩,例如下面這段新生代收集器ParNew的日志也會出現(xiàn)“[Full GC”(這一般是因為出現(xiàn)了分配擔(dān)保失敗之類的問題铁孵,所以才導(dǎo)致STW)。如果是調(diào)用System.gc()方法所觸發(fā)的收集房资,那么在這里將顯示“[Full GC(System)”蜕劝。

接下來的“[DefNew”、“[Tenured”轰异、“[Perm”表示GC發(fā)生的區(qū)域岖沛,這里顯示的區(qū)域名稱與使用的GC收集器是密切相關(guān)的,例如上面樣例所使用的Serial收集器中的新生代名為“DefaultNew Generation”搭独,所以顯示的是“[DefNew”婴削。如果是ParNew收集器,新生代名稱就會變?yōu)椤癧ParNew”牙肝,意為“Parallel New Generation”唉俗。如果采用Parallel Scavenge收集器,那它配套的新生代稱為“PSYoungGen”配椭,老年代和永久代同理虫溜,名稱也是由收集器決定的。

后面方括號內(nèi)部的“3324K->152K(3712K)”含義是“GC前該內(nèi)存區(qū)域已使用容量->GC后該內(nèi)存區(qū)域已使用容量(該內(nèi)存區(qū)域總?cè)萘浚惫筛住6诜嚼ㄌ栔獾摹?324K->152K(11904K)”表示“GC前Java堆已使用容量->GC后Java堆已使用容量(Java堆總?cè)萘浚薄?/p>

再往后吼渡,“0.0025925 secs”表示該內(nèi)存區(qū)域GC所占用的時間,單位是秒乓序。有的收集器會給出更具體的時間數(shù)據(jù)寺酪,如“[Times:user=0.01 sys=0.00坎背,real=0.02 secs]”,這里面的user寄雀、sys和real與Linux的time命令所輸出的時間含義一致得滤,分別代表用戶態(tài)消耗的CPU時間、內(nèi)核態(tài)消耗的CPU事件和操作從開始到結(jié)束所經(jīng)過的墻鐘時間(Wall Clock Time)盒犹。CPU時間與墻鐘時間的區(qū)別是懂更,墻鐘時間包括各種非運(yùn)算的等待耗時,例如等待磁盤I/O急膀、等待線程阻塞沮协,而CPU時間不包括這些耗時,但當(dāng)系統(tǒng)有多CPU或者多核的話卓嫂,多線程操作會疊加這些
CPU時間慷暂,所以讀者看到user或sys時間超過real時間是完全正常的。

[GC (Allocation Failure) [DefNew: 707K->476K(4928K), 0.0013631 secs]
[Tenured: 0K->476K(10944K), 0.0024463 secs] 707K->476K(15872K), 
[Metaspace: 1640K->1640K(4480K)], 0.0238666 secs] [Times: user=0.00 
sys=0.00, real=0.02 secs] 
[GC (Allocation Failure) [DefNew: 0K->0K(4992K), 0.0003036 secs]
[Tenured: 20956K->475K(31428K), 0.0017487 secs] 20956K-
 >475K(36420K), [Metaspace: 1640K->1640K(4480K)], 0.0021762 secs] 
[Times: user=0.02 sys=0.00, real=0.00 secs] 
[Full GC (System.gc()) [Tenured: 20955K->475K(31428K), 0.0019586 secs] 21208K->475K(45636K), [Metaspace: 1640K->1640K(4480K)], 0.0185442 secs] [Times: user=0.00 sys=0.00, real=0.02 secs] 
Heap
  def new generation   total 13248K, used 235K [0x03e00000, 0x04c60000, 0x09350000)
  eden space 11776K,   2% used [0x03e00000, 0x03e3af90, 0x04980000)
  from space 1472K,   0% used [0x04980000, 0x04980000, 0x04af0000)
  to   space 1472K,   0% used [0x04af0000, 0x04af0000, 0x04c60000)
  tenured generation   total 29380K, used 475K [0x09350000, 0x0b001000, 0x13e00000)
  the space 29380K,   1% used [0x09350000, 0x093c6e10, 0x093c7000, 0x0b001000)
  Metaspace       used 1644K, capacity 2242K, committed 2368K, reserved 4480K
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晨雳,一起剝皮案震驚了整個濱河市行瑞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌餐禁,老刑警劉巖血久,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異帮非,居然都是意外死亡氧吐,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門末盔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來副砍,“玉大人,你說我怎么就攤上這事庄岖。” “怎么了角骤?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵隅忿,是天一觀的道長。 經(jīng)常有香客問我邦尊,道長背桐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任蝉揍,我火速辦了婚禮链峭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘又沾。我一直安慰自己弊仪,他們只是感情好熙卡,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著励饵,像睡著了一般驳癌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上役听,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天颓鲜,我揣著相機(jī)與錄音,去河邊找鬼典予。 笑死甜滨,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瘤袖。 我是一名探鬼主播衣摩,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼孽椰!你這毒婦竟也來了昭娩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤黍匾,失蹤者是張志新(化名)和其女友劉穎栏渺,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锐涯,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡磕诊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了纹腌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片霎终。...
    茶點(diǎn)故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖升薯,靈堂內(nèi)的尸體忽然破棺而出莱褒,到底是詐尸還是另有隱情,我是刑警寧澤涎劈,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布广凸,位于F島的核電站,受9級特大地震影響蛛枚,放射性物質(zhì)發(fā)生泄漏谅海。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一蹦浦、第九天 我趴在偏房一處隱蔽的房頂上張望扭吁。 院中可真熱鬧,春花似錦、人聲如沸侥袜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽系馆。三九已至送漠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間由蘑,已是汗流浹背闽寡。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尼酿,地道東北人爷狈。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像裳擎,于是被迫代替她去往敵國和親涎永。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評論 2 349

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