摘要:語(yǔ)言使用了內(nèi)存動(dòng)態(tài)分配和垃圾回收技術(shù),掌握這些不僅可以提高自己的逼格,而且為后續(xù)的調(diào)優(yōu)打下扎實(shí)的基礎(chǔ),讓自己離架構(gòu)師更近一步。任何引用計(jì)數(shù)器為的對(duì)象實(shí)例可以被當(dāng)作垃圾收集。引用計(jì)數(shù)是垃圾收集器中的早期策略。
JVM之垃圾回收
市面上有關(guān)JVM垃圾回收的文章很多,有些是針對(duì)垃圾收集器,有些是介紹垃圾回收算法,也有些各方面都有涉及。本文希望能做一個(gè)比較全面的總結(jié),最關(guān)鍵的是形成自己的語(yǔ)言,有自己的理解和沉淀。
一、為什么需要垃圾回收大家都知道,java語(yǔ)言的內(nèi)存是動(dòng)態(tài)分配的,不像C++語(yǔ)言還需要開發(fā)者專門干預(yù),在一定程度上可以提高開發(fā)效率。那么大家可能疑問:既然不需要我們開發(fā)者關(guān)心,我們?yōu)槭裁催€要討論?作為一個(gè)程序語(yǔ)言的駕馭者,必然需要掌握該語(yǔ)言的方方面面,包括底層的原理和機(jī)制。
Java語(yǔ)言使用了內(nèi)存動(dòng)態(tài)分配和垃圾回收技術(shù),掌握這些不僅可以提高自己的逼格,而且為后續(xù)的JVM調(diào)優(yōu)打下扎實(shí)的基礎(chǔ),讓自己離架構(gòu)師更近一步。
JVM的內(nèi)存結(jié)構(gòu)包括五大區(qū)域:程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧、堆區(qū)、方法區(qū)。其中程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧3個(gè)區(qū)域隨線程而生、隨線程而滅,因此這幾個(gè)區(qū)域的內(nèi)存分配和回收都具備確定性,就不需要過(guò)多考慮回收的問題,因?yàn)榉椒ńY(jié)束或者線程結(jié)束時(shí),內(nèi)存自然就跟隨著回收了。而Java堆區(qū)和方法區(qū)則不一樣,這部分內(nèi)存的分配和回收是動(dòng)態(tài)的,正是垃圾收集器所需關(guān)注的部分。
垃圾收集器在對(duì)堆區(qū)和方法區(qū)進(jìn)行回收前,首先要確定這些區(qū)域的對(duì)象哪些可以被回收,哪些暫時(shí)還不能回收,這就要用到判斷對(duì)象是否存活的算法。
1、引用計(jì)數(shù)法
在這種方法中,堆中每個(gè)對(duì)象實(shí)例都有一個(gè)引用計(jì)數(shù)。任何引用計(jì)數(shù)器為0的對(duì)象實(shí)例可以被當(dāng)作垃圾收集。
引用計(jì)數(shù)是垃圾收集器中的早期策略。該方法看似很實(shí)用,但是解決不了循環(huán)引用的問題(比如循環(huán)鏈表)。
2、可達(dá)性分析算法
從一個(gè)節(jié)點(diǎn)GC ROOT開始,尋找對(duì)應(yīng)的引用節(jié)點(diǎn),然后尋該引用節(jié)點(diǎn)的引用節(jié)點(diǎn),當(dāng)所有的引用節(jié)點(diǎn)尋找完畢之后,剩余沒有被引用的節(jié)點(diǎn)將會(huì)被判定為是可回收的對(duì)象。
3、引用分類
在Java語(yǔ)言中,將引用又分為強(qiáng)引用、軟引用、弱引用、虛引用四種,這四種引用強(qiáng)度依次逐漸減弱。垃圾回收算法都是基于強(qiáng)引用而言的。
三、垃圾回收算法1、標(biāo)記-清除算法
標(biāo)記-清除算法從根集合(GC Roots)開始掃描,對(duì)需要繼續(xù)存活的對(duì)象進(jìn)行標(biāo)記,標(biāo)記完畢后,再掃描整個(gè)空間中未被標(biāo)記的對(duì)象,進(jìn)行回收,如下圖所示。
標(biāo)記-清除算法只需對(duì)不需要存活的對(duì)象進(jìn)行處理,在存活對(duì)象比較多的情況下極為高效,但是會(huì)造成內(nèi)存碎片。
2、復(fù)制算法
復(fù)制算法的提出就是為了解決內(nèi)存碎片的問題,如下圖所示。復(fù)制算法雖然解決了內(nèi)存碎片的問題,但是浪費(fèi)一半內(nèi)存。另外在對(duì)象存活率很高的時(shí)候,復(fù)制成本會(huì)非常高。
3、標(biāo)記-整理算法
標(biāo)記-整理算法是在標(biāo)記-清除算法的基礎(chǔ)上,又進(jìn)行了對(duì)象的移動(dòng),因此成本更高,但是卻解決了內(nèi)存碎片的問題。具體流程見下圖:
4、分代收集算法
一般情況下將堆區(qū)劃分為老年代(Tenured Generation)和新生代(Young Generation),老年代的特點(diǎn)是每次垃圾收集時(shí)只有少量對(duì)象需要被回收,而新生代的特點(diǎn)是每次垃圾回收時(shí)都有大量的對(duì)象需要被回收,那么就可以根據(jù)不同代的特點(diǎn)采取最適合的收集算法。
新生代采用復(fù)制算法;老年代采用標(biāo)記-整理算法。
其中年輕代內(nèi)存分配過(guò)程如下:
1) 絕大多數(shù)剛創(chuàng)建的對(duì)象會(huì)被分配在Eden區(qū),其中的大多數(shù)對(duì)象很快就會(huì)消亡;
2) 最初一次,當(dāng)Eden區(qū)滿的時(shí)候,執(zhí)行Minor GC,將消亡的對(duì)象清理掉,并將剩余的對(duì)象復(fù)制到一個(gè)存活區(qū)Survivor0;
3) 下次Eden區(qū)滿了,再執(zhí)行一次Minor GC,將消亡的對(duì)象清理掉,將存活的對(duì)象復(fù)制到Survivor1中,然后清空Eden區(qū);
4) 將Survivor0中消亡的對(duì)象清理掉,將其中可以晉級(jí)的對(duì)象晉級(jí)到Old區(qū),將存活的對(duì)象也復(fù)制到Survivor1區(qū),然后清空Survivor0區(qū);
5) 然后跳到第三步,當(dāng)兩個(gè)存活區(qū)切換了幾次(HotSpot虛擬機(jī)默認(rèn)15次,用-XX:MaxTenuringThreshold控制)之后,仍然存活的對(duì)象,將被復(fù)制到老年代。
1、新生代收集器
1) Serial收集器
單線程收集器
2) ParaNew收集器
Serial收集器的多線程版,關(guān)注縮短垃圾收集時(shí)間。(使用-XX:+UseParNewGC開關(guān)來(lái)控制使用ParNew+Serial Old收集器組合收集內(nèi)存;使用-XX:ParallelGCThreads來(lái)設(shè)置執(zhí)行內(nèi)存回收的線程數(shù)。)
3) Parallel Scavenge收集器
關(guān)注CPU吞吐量,即運(yùn)行用戶代碼的時(shí)間/總時(shí)間。(使用-XX:+UseParallelGC開關(guān)控制使用Parallel Scavenge+Serial Old收集器組合回收垃圾(這也是在Server模式下的默認(rèn)值);使用-XX:GCTimeRatio來(lái)設(shè)置用戶執(zhí)行時(shí)間占總時(shí)間的比例,默認(rèn)99,即1%的時(shí)間用來(lái)進(jìn)行垃圾回收;使用-XX:MaxGCPauseMillis設(shè)置GC的最大停頓時(shí)間;使用-XX:+UseAdaptiveSizePolicy可以進(jìn)行動(dòng)態(tài)控制Eden/Survivor比例,老年代對(duì)象年齡,新生代大小等。)
2、老年代收集器
1) Serial Old收集器
單線程收集器
2) Parallel Old收集器
Parallel Scavenge收集器的老年代版本(使用-XX:+UseParallelOldGC開關(guān)控制使用Parallel Scavenge +Parallel Old組合收集器進(jìn)行收集。)
3) CMS收集器
多線程,優(yōu)點(diǎn)是并發(fā)收集(用戶線程可以和GC線程同時(shí)工作)
3、G1收集器
特性:
1) 首先收集盡可能多的垃圾(Garbage First)
內(nèi)部采用了啟發(fā)式算法,找出具有高收集收益的分區(qū)進(jìn)行收集。
2) 并行和并發(fā)
和CMS相似,可以做到用戶線程和GC線程同時(shí)工作。
3) 內(nèi)存布局調(diào)整
將整個(gè)堆劃分為多個(gè)大小相等的獨(dú)立區(qū)域(Region),新生代和老年代不再是物理隔離,它們都是一部分Region(不需要連續(xù))的集合。每個(gè)分區(qū)都可能隨G1的運(yùn)行在不同代之間前后切換。
G1劃分了一個(gè)Humongous區(qū),它用來(lái)專門存放巨型對(duì)象。
4) GC模式
G1提供了兩種GC模式,Young GC和Mixed GC,兩種都是Stop The World(STW)的。
[1] https://blog.csdn.net/ft30597...
[2] https://www.cnblogs.com/1024C...
[3] https://blog.csdn.net/x_i_y_u...
[4] https://www.jianshu.com/p/e99...
[5] https://blog.csdn.net/foolish...
[6] https://blog.csdn.net/coderli...
[7] https://www.cnblogs.com/ASPNE...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/72586.html
摘要:垃圾回收算法與垃圾回收器綜述我們常說(shuō)的垃圾回收算法可以分為兩部分對(duì)象的查找算法與真正的回收方法。串行垃圾回收器一次只使用一個(gè)線程進(jìn)行垃圾回收并行垃圾回收器一次將開啟多個(gè)線程同時(shí)進(jìn)行垃圾回收。 垃圾回收算法與 JVM 垃圾回收器綜述歸納于筆者的 JVM 內(nèi)部原理與性能調(diào)優(yōu)系列文章,文中涉及的引用資料參考 Java 學(xué)習(xí)與實(shí)踐資料索引、JVM 資料索引。 showImg(https://s...
摘要:年輕代的目標(biāo)就是盡可能快速的收集掉那些生命周期短的對(duì)象。年老代在年輕代中經(jīng)歷了次垃圾回收后仍然存活的對(duì)象,就會(huì)被放到年老代中。什么情況下觸發(fā)垃圾回收由于對(duì)象進(jìn)行了分代處理,因此垃圾回收區(qū)域時(shí)間也不一樣。 [TOC] 與C/C++相比,java語(yǔ)言不需要程序員直接控制內(nèi)存回收,java程序的內(nèi)存分配和回收都是由JRE在后臺(tái)自動(dòng)進(jìn)行,JRE會(huì)負(fù)責(zé)回收那些不再使用的內(nèi)存,這種機(jī)制被稱為垃圾...
摘要:本人使用的是,以下涉及的默認(rèn)值均以該版本為準(zhǔn)。其中,新生代被細(xì)分為和兩個(gè)區(qū)域,這兩個(gè)區(qū)域分別被命名為和,以示區(qū)分。其中新生帶存放新生的對(duì)象或者年齡不大的對(duì)象,老年代則存放老年對(duì)象。 什么是垃圾回收機(jī)制 不定時(shí)去堆內(nèi)存中清理不可達(dá)對(duì)象。不可達(dá)的對(duì)象并不會(huì)馬上就會(huì)直接回收, 垃圾收集器在一個(gè)Java程序中的執(zhí)行是自動(dòng)的,不能強(qiáng)制執(zhí)行,即使程序員能明確地判斷出有一塊內(nèi)存已經(jīng)無(wú)用了,是應(yīng)該回收...
摘要:直接對(duì)棧的操作只有兩個(gè),就是對(duì)棧幀的壓棧和出棧。中將永久代移除,同時(shí)增加元數(shù)據(jù)區(qū)。在中,本地方法棧和虛擬機(jī)棧是在同一塊兒區(qū)域,這完全取決于技術(shù)實(shí)現(xiàn)的決定,并未在規(guī)范中強(qiáng)制。 原文:https://github.com/linsheng97... 描述一下 JVM 的內(nèi)存區(qū)域 程序計(jì)數(shù)?(PC,Program Counter Register)。在 JVM 規(guī)范中,每個(gè)線程都有它自己的...
摘要:概要要理解的內(nèi)存管理策略,首先就要熟悉的運(yùn)行時(shí)數(shù)據(jù)區(qū),如上圖所示,在執(zhí)行程序的時(shí)候,虛擬機(jī)會(huì)把它所管理的內(nèi)存劃分為多個(gè)不同的數(shù)據(jù)區(qū),稱為運(yùn)行時(shí)數(shù)據(jù)區(qū)。 這是一篇有關(guān)JVM內(nèi)存管理的文章。這里將會(huì)簡(jiǎn)單的分析一下Java如何使用從物理內(nèi)存上申請(qǐng)下來(lái)的內(nèi)存,以及如何來(lái)劃分它們,后面還會(huì)介紹JVM的核心技術(shù):如何分配和回收內(nèi)存。 JMM ( Java Memory Model )概要 show...
閱讀 2293·2021-11-25 09:43
閱讀 3446·2021-10-25 09:48
閱讀 1321·2021-09-13 10:24
閱讀 2735·2019-08-29 15:07
閱讀 1258·2019-08-29 13:14
閱讀 3265·2019-08-29 12:22
閱讀 1354·2019-08-29 11:32
閱讀 3229·2019-08-29 11:23