自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一文吃透 JVM 中的垃圾收集器

開發(fā) 前端
在 JDK1.8 及之后的版本中,用元空間來作為方法區(qū)的實(shí)現(xiàn),元空間的內(nèi)存空間默認(rèn)使用的是操作系統(tǒng)的內(nèi)存空間,它的垃圾回收不再由 Java 來控制,元空間的內(nèi)存管理由元空間虛擬機(jī)來完成。

01、背景介紹

今天通過這篇文章,結(jié)合之前的知識(shí),我們一起來了解一下 JVM 中的垃圾收集器。

02、垃圾收集器

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

不同的虛擬機(jī)所提供的垃圾收集器可能會(huì)有很大差異,以 HotSpot 虛擬機(jī)為例,所包含的垃圾收集器可以用如下圖來概括。

圖片圖片

上圖中的連線表示,不同分代的收集器可以搭配使用。

  • 新生代收集器:Serial、ParNew、Parallel Scavenge
  • 老年代收集器:Serial Old、CMS、Parallel Old
  • 通用收集器:G1

在虛擬機(jī)中,沒有所謂的萬(wàn)能收集器,只有根據(jù)具體的業(yè)務(wù)場(chǎng)景,選擇最合適的收集器。這也是為什么 HotSpot 實(shí)現(xiàn)了這么多收集器的原因。

下面我們一起來看看相關(guān)的具體實(shí)現(xiàn)。

2.1、Serial 和 Serial Old收集器

Serial 系列的垃圾收集器是 JVM 的第一款收集器,它的設(shè)計(jì)思路很簡(jiǎn)單,在新生代,使用單線程采用復(fù)制算法進(jìn)行收集對(duì)象;在老年代,使用單線程采用標(biāo)記整理算法進(jìn)行收集對(duì)象;垃圾收集的過程中會(huì)暫停用戶線程,直到垃圾收集完畢。

因?yàn)楫?dāng)時(shí)的硬件環(huán)境配置都不高,內(nèi)存都是幾十兆,CPU 也都是單核的,不像現(xiàn)在這樣處處都是高并發(fā)的應(yīng)用場(chǎng)景。限于當(dāng)時(shí)的硬件資源和應(yīng)用場(chǎng)景,這個(gè)收集器優(yōu)勢(shì)很突出,簡(jiǎn)單高效、消耗資源也很少。

唯一的不足在于,在用戶不可見的情況下要把用戶正常工作的線程全部停掉,這對(duì)很多應(yīng)用比較難以接受。不過實(shí)際上到目前為止,Serial 收集器依然是虛擬機(jī)在 Client 模式下運(yùn)行的默認(rèn)新生代收集器,因?yàn)樗?jiǎn)單而高效??蛻舳藨?yīng)用模型下,分配給虛擬機(jī)管理的內(nèi)存一般來說不會(huì)很大,收集幾十兆甚至一兩百兆的新生代對(duì)象,停頓時(shí)間平均在幾十毫秒,只要不是頻繁收集,完全可以接受。

整個(gè)流程,可以用如下圖來概括。

圖片圖片

總結(jié)下來,收集器特點(diǎn)如下:

  • 收集區(qū)域:Serial(新生代),Serial Old(老年代)
  • 收集算法:Serial(復(fù)制算法),Serial Old(標(biāo)記整理算法)
  • 收集方式:?jiǎn)尉€程
  • 優(yōu)勢(shì):簡(jiǎn)單高效,內(nèi)存資源占用少,單核 CPU 環(huán)境最佳選項(xiàng)
  • 劣勢(shì):整個(gè)搜集過程需要停頓用戶線程,多核 CPU、大內(nèi)存的環(huán)境,資源優(yōu)勢(shì)無法發(fā)揮起來

2.2、ParNew收集器

ParNew 收集器,可以看成是 Serial 收集器的多線程版本。除了使用多線程進(jìn)行垃圾收集外,其余行為和 Serial 收集器完全一樣,包括使用的也是復(fù)制算法,垃圾收集時(shí)暫停用戶線程。在多核 CPU 資源環(huán)境下,可以顯著提升整個(gè)垃圾收集的性能,也是虛擬機(jī)在 Server 模式下運(yùn)行的首選新生代收集器。

能讓 ParNew 出名的一個(gè)核心因素是,它是除了 Serial 收集器外,目前唯一一個(gè)能與 CMS 收集器配合一起使用的新生代收集器,因?yàn)?CMS 優(yōu)秀所以 ParNew 也出名了,有點(diǎn)類似碰上了大款的感覺,其中 CMS 收集器是一款幾乎可以認(rèn)為有劃時(shí)代意義的垃圾收集器,下文我們?cè)僦v。

其次,ParNew 收集器在單個(gè) CPU 的環(huán)境中絕對(duì)不會(huì)有比 Serial 收集器更好的效果,甚至由于線程交互的開銷,該收集器在兩個(gè) CPU 的環(huán)境中都不能百分之百保證可以超越 Serial 收集器。當(dāng)然,隨著可用 CPU 數(shù)量的增加,它對(duì)于垃圾收集的效率提升還是很有幫助的。

整個(gè)流程,可以用如下圖來概括。

圖片圖片

總結(jié)下來,收集器特點(diǎn)如下:

  • 收集區(qū)域:新生代
  • 收集算法:復(fù)制算法
  • 收集方式:多線程
  • 優(yōu)勢(shì):多線程收集,多核 CPU 環(huán)境下效率要比 serial 高,新生代中,除了 Serial 收集器外目前唯一一個(gè)能與 CMS 配合的收集器
  • 劣勢(shì):整個(gè)搜集過程需要停頓用戶線程

3.3、Parallel Scavenge 和 Parallel Old收集器

Parallel Scavenge 和 ParNew 收集器很類似,也是一款使用多線程采用復(fù)制算法的新生代收集器;Parallel Old 收集器是一款使用多線程采用標(biāo)記整理算法的老年代收集器;垃圾收集過程中也會(huì)暫停用戶線程,直到整個(gè)垃圾收集過程結(jié)束。

不同的是,Parallel 收集器更關(guān)注系統(tǒng)的吞吐量,也被稱為“吞吐量?jī)?yōu)先收集器”。

所謂吞吐量的意思就是 CPU 用于運(yùn)行用戶代碼時(shí)間與 CPU 總消耗時(shí)間的比值,即吞吐量=運(yùn)行用戶代碼時(shí)間/(運(yùn)行用戶代碼時(shí)間+垃圾收集時(shí)間),比如虛擬機(jī)總運(yùn)行 100 分鐘,垃圾收集 1 分鐘,那吞吐量就是 99%。高吞吐量可以高效率的利用 CPU 資源,盡快完成程序的運(yùn)算任務(wù),主要適合在后臺(tái)運(yùn)算而不需要太多交互的任務(wù)。

自適應(yīng)調(diào)節(jié)策略也是 Parallel Scavenge 與 ParNew 的一個(gè)重要區(qū)別,用戶可以通過參數(shù)來打開自適應(yīng)調(diào)節(jié)策略,比如-XX:+UseAdaptiveSizePolicy參數(shù),打開之后就不需要手動(dòng)指定新生代大小、Eden 區(qū)和 Survivor 參數(shù)等細(xì)節(jié)參數(shù)了,虛擬機(jī)會(huì)根據(jù)當(dāng)前系統(tǒng)的運(yùn)行情況收集性能監(jiān)控信息,動(dòng)態(tài)調(diào)整這些參數(shù)以提供最合適的停頓時(shí)間或最大的吞吐量。如果對(duì)于垃圾收集器運(yùn)作原理不太了解,優(yōu)化比較困難的情況下,使用 Parallel 收集器配合自適應(yīng)調(diào)節(jié)策略,把內(nèi)存管理的調(diào)優(yōu)任務(wù)交給虛擬機(jī)去完成也是一個(gè)不錯(cuò)的選擇。

另外,Parallel 收集器是虛擬機(jī)在 Server 模式下運(yùn)行的默認(rèn)垃圾收集器。

整個(gè)執(zhí)行流程,跟 ParNew 收集器類似。

總結(jié)下來,收集器特點(diǎn)如下:

  • 收集區(qū)域:Parallel Scavenge(新生代),Parallel Old(老年代)
  • 收集算法:Parallel Scavenge(復(fù)制算法),Parallel Old(標(biāo)記整理算法)
  • 收集方式:多線程
  • 優(yōu)勢(shì):多線程收集,多核 CPU 環(huán)境下效率要比 serial 高
  • 劣勢(shì):整個(gè)搜集過程需要停頓用戶線程

2.4、CMS收集器

CMS 收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)的老年代收集器。

與前面幾個(gè)收集器不同,它采用了一種全新的策略可以在垃圾回收過程中的某些階段用戶線程和垃圾回收線程一起工作,從而避免了因?yàn)殚L(zhǎng)時(shí)間的垃圾回收而使用戶線程一直處于等待之中。

目前很大一部分 Java 應(yīng)用集中在互聯(lián)網(wǎng)站或者 B/S 系統(tǒng)的服務(wù)端上,這類應(yīng)用尤其注重服務(wù)的響應(yīng)速度,希望系統(tǒng)停頓時(shí)間最短,比如在一個(gè)長(zhǎng)度為 M 毫秒的時(shí)間片段內(nèi),消耗在垃圾收集上的時(shí)間不得超過多少毫秒,以期給用戶帶來較好的體驗(yàn),其中 CMS 收集器就非常符合這類應(yīng)用的需求。

CMS 的英文全程是:Concurrent Mark-Sweep Collector,從名字上就能看出 CMS 收集器是基于“標(biāo)記-清除”算法實(shí)現(xiàn)的,它的運(yùn)作過程相對(duì)于前面幾種收集器來說要更復(fù)雜一些,整個(gè)過程分為如下 4 個(gè)步驟:

  • 初始標(biāo)記
  • 并發(fā)標(biāo)記
  • 重新標(biāo)記
  • 并發(fā)清除

CMS 會(huì)根據(jù)每個(gè)階段不同的特性來決定是否停頓用戶線程。整個(gè)流程,可以用如下圖來概括。(圖片來自于勤勞的小手 - 垃圾收集器文章)

圖片圖片

2.4.1、階段一:初始標(biāo)記

初始標(biāo)記階段的工作主要是標(biāo)記一下 GC Roots 能直接關(guān)聯(lián)到的對(duì)象,這個(gè)過程會(huì)短暫的停頓用戶線程,因?yàn)椴⒉粫?huì)對(duì)整個(gè) GC Roots 的引用進(jìn)行遍歷,因此速度很快。

2.4.2、階段二:并發(fā)標(biāo)記

并發(fā)標(biāo)記階段的工作主要是把階段一標(biāo)記好的 GC Roots 對(duì)象進(jìn)行深度的遍歷,找到所有與 GC Roots 關(guān)聯(lián)的對(duì)象并進(jìn)行標(biāo)記,這個(gè)過程會(huì)采用多線程的方式進(jìn)行遍歷標(biāo)記,因?yàn)榉浅:臅r(shí),CMS 考慮到為了盡量不停頓用戶線程,因此這個(gè)階段不會(huì)暫停用戶線程,也就是說,此時(shí) JVM 會(huì)分配一些資源給用戶線程執(zhí)行任務(wù),通過這樣的方式減少用戶線程的停頓時(shí)間。

2.4.3、階段三:重新標(biāo)記

重新標(biāo)記階段的工作主要是修補(bǔ)階段二用戶線程運(yùn)行期間產(chǎn)生新的垃圾對(duì)象,進(jìn)行重新標(biāo)記,同樣也是采用多線程方式進(jìn)行,此階段數(shù)量不會(huì)很多,會(huì)短暫的停頓用戶線程,速度也很快。

2.4.4、階段四:并發(fā)清除

并發(fā)清除階段的工作主要是對(duì)那些被標(biāo)記為可回收的對(duì)象進(jìn)行清理,在一般情況下,并發(fā)清除階段是使用的是“標(biāo)記-清除”算法,因?yàn)檫@個(gè)過程不會(huì)牽扯到對(duì)象的地址變更,所以 CMS 在并發(fā)清除階段是不需要停止用戶線程的,對(duì)象回收效率非常高。

與此同時(shí),正因?yàn)椴l(fā)清除階段用戶線程也可以同時(shí)運(yùn)行,所以在用戶線程運(yùn)行的過程中自然也會(huì)產(chǎn)生新的垃圾對(duì)象,這也就是導(dǎo)致 CMS 收集器會(huì)產(chǎn)生“浮動(dòng)垃圾”的原因,此時(shí)也會(huì)產(chǎn)生很多的空間碎片,當(dāng)空間碎片到達(dá)了一定程度時(shí),此時(shí) CMS 就會(huì)使用“標(biāo)記-整理”算法來解決空間碎片的問題。

在上文的垃圾回收算法中我們有說到,“標(biāo)記-整理”算法會(huì)將對(duì)象的位置進(jìn)行挪動(dòng)并更新對(duì)象的引用的指向地址,在這個(gè)過程中,如果用戶線程同時(shí)運(yùn)行的話會(huì)產(chǎn)生并發(fā)問題,因此當(dāng) CMS 進(jìn)行碎片整理的時(shí)候必須得停止用戶線程。所以,在某些情況下,并發(fā)清除階段 CMS 也會(huì)停頓用戶線程。

CMS 收集器作為一個(gè)全新思路的垃圾收集器,雖然很優(yōu)秀,但一直沒有被 Hospot 虛擬機(jī)納入為默認(rèn)的垃圾收集器。時(shí)至今日,JDK1.8 使用的默認(rèn)收集器都還是 Parallel scavenge 和 Parallel old 收集器,主要原因在于 CMS 存在一些比較頭疼的問題,比如浮動(dòng)垃圾、空間碎片整理時(shí)會(huì)造成系統(tǒng)卡頓、在并發(fā)清除階段可能會(huì)出現(xiàn)系統(tǒng)長(zhǎng)時(shí)間的假死。

2.4.5、小結(jié)

總結(jié)下來,收集器特點(diǎn)如下:

  • 收集區(qū)域:老年代
  • 收集算法:標(biāo)記清除算法 + 標(biāo)記整理算法
  • 收集方式:多線程
  • 優(yōu)勢(shì):多線程收集過程中可以做到不停止用戶線程,以獲取最短回收停頓時(shí)間
  • 劣勢(shì):會(huì)產(chǎn)生浮動(dòng)垃圾、空間碎片整理時(shí)會(huì)造成系統(tǒng)卡頓、并發(fā)清除階段可能會(huì)出現(xiàn)系統(tǒng)假死等問題

2.5、G1收集器

G1(Garbage-First)收集器是當(dāng)今收集器技術(shù)發(fā)展的最前沿成果之一,從 JDK 7 Update 4 后開始進(jìn)入商用。

在 G1 收集器出現(xiàn)之前,不管是 Serial 系列,Parallel 系列,還是 CMS 收集器,它們都是基于把內(nèi)存進(jìn)行物理分區(qū)的形式將 JVM 內(nèi)存分成新生代、老年代、永久代或 MetaSpace,這種分區(qū)模式下進(jìn)行垃圾收集時(shí)必須對(duì)某個(gè)區(qū)域進(jìn)行整體性的收集,比如整個(gè)新生代、整個(gè)老年代收集或者整個(gè)堆,當(dāng)內(nèi)存空間不大的時(shí)候,比如幾個(gè) G,通過參數(shù)優(yōu)化能取得不錯(cuò)的收集性能。但是,隨著硬件資源的發(fā)展,JVM 可用內(nèi)存從幾十 G 到幾百 G 甚至上 T 時(shí),這種采用傳統(tǒng)模式下的物理分區(qū)進(jìn)行收集時(shí),每次掃描內(nèi)存的區(qū)域自然就變大了,進(jìn)行垃圾清理的時(shí)間自然就變得更長(zhǎng)了,此時(shí)傳統(tǒng)的收集器即時(shí)再怎么優(yōu)化,也難以取得令人滿意的收集效果,因此需要一款全新的垃圾收集器。

G1 收集器就是在這樣的環(huán)境下誕生的,它摒棄了原來的物理分區(qū),把整個(gè) Java 堆分成若干個(gè)大小相等的獨(dú)立區(qū)域(Region),雖然還保留有新生代和老年代的概念,但新生代和老年代不再是物理隔離,它們都是一部分 Region 的集合。從結(jié)構(gòu)上看,G1 收集器不要求整個(gè)新生代或者老年代都是連續(xù)的,也不再堅(jiān)持固定大小和固定數(shù)量,它會(huì)跟蹤各個(gè) Region 里面的垃圾堆積的價(jià)值大小,在后臺(tái)維護(hù)一個(gè)優(yōu)先列表,每次根據(jù)允許的收集時(shí)間,優(yōu)先回收價(jià)值最大的 Region。這種通過 Region 劃分內(nèi)存空間以及有優(yōu)先級(jí)的區(qū)域回收方式,保證了 G1 收集器在有限的時(shí)間內(nèi)可以獲取盡可能高的收集效率。

G1 收集器內(nèi)存劃分,可以用如下圖來概括。(圖片來自于勤勞的小手 - 垃圾收集器文章)

圖片圖片

在 G1 收集器里面維護(hù)了一個(gè) Collect Set 集合,這個(gè)集合里面記錄了待回收的 Region 區(qū)域信息,同時(shí)也包括了每個(gè) Region 區(qū)域可回收的大小空間。通過 Collect Set 里面的信息,G1 在進(jìn)行垃圾收集時(shí),可以根據(jù)用戶設(shè)定的可接受停頓時(shí)間來進(jìn)行分析,在設(shè)定的時(shí)間范圍內(nèi)優(yōu)先收集垃圾最多的 Region 區(qū)域,以實(shí)現(xiàn)高吞吐、低停頓的收集效果。

在工作流程上,G1 收集器也吸收了 CMS 很多優(yōu)秀的收集思路,整個(gè)垃圾收集過程,可以分為如下 4 個(gè)步驟:

  • 初始標(biāo)記
  • 并發(fā)標(biāo)記
  • 重新標(biāo)記
  • 篩選回收

G1 收集器的垃圾回收流程和 CMS 邏輯大致相同,主要的區(qū)別在最后一個(gè)階段,G1 不會(huì)直接進(jìn)行清除,而是會(huì)根據(jù)設(shè)置的停頓時(shí)間進(jìn)行智能的篩選和局部的回收,采用“標(biāo)記復(fù)制”算法來實(shí)現(xiàn)。

整個(gè)流程,可以用如下圖來概括。

圖片圖片

2.5.1、階段一:初始標(biāo)記

此階段的工作內(nèi)容與上文介紹的 CMS 收集器一樣,會(huì)先把所有 GC Roots 直接引用的對(duì)象進(jìn)行標(biāo)記,同時(shí)會(huì)短暫的停止用戶線程,因?yàn)椴粫?huì)對(duì)整個(gè) GC Roots 的引用進(jìn)行遍歷,因此速度比較快。

2.5.2、階段二:并發(fā)標(biāo)記

此階段的工作內(nèi)容與上文介紹的 CMS 收集器也一樣,找到所有與 GC Roots 關(guān)聯(lián)的對(duì)象并進(jìn)行深度遍歷標(biāo)記,會(huì)采用多線程的方式進(jìn)行遍歷標(biāo)記,因?yàn)楸容^耗時(shí),為了盡量不停頓用戶線程,這個(gè)階段 GC 線程會(huì)和用戶線程同時(shí)運(yùn)行,通過這樣的方式減少用戶線程的停頓時(shí)間。

2.5.3、階段三:重新標(biāo)記

此階段的工作內(nèi)容與上文介紹的 CMS 收集器也是一樣,針對(duì)階段二用戶線程運(yùn)行的過程中產(chǎn)生新的垃圾,采用多線程方式進(jìn)行重新標(biāo)記,為了避免這個(gè)過程再次產(chǎn)生新的垃圾對(duì)象,會(huì)短暫的停止用戶線程,因?yàn)閿?shù)量不會(huì)很多,因此速度比較快。

2.5.4、階段四:篩選回收

篩選回收階段的工作主要是把存活的對(duì)象復(fù)制到 Region 空閑區(qū)域,同時(shí)會(huì)根據(jù) Collect Set 記錄的可回收 Region 信息進(jìn)行篩選,計(jì)算 Region 回收成本,接著根據(jù)用戶設(shè)定的停頓時(shí)間值制定回收計(jì)劃,最后根據(jù)回收計(jì)劃篩選合適的 Region 區(qū)域進(jìn)行垃圾回收。

從局部來看,G1 使用的是復(fù)制算法,將存活對(duì)象從一個(gè) Region 區(qū)域復(fù)制到另一個(gè) Region 空閑區(qū)域;但從整個(gè)堆來看,G1 使用的邏輯又相當(dāng)于標(biāo)記整理算法,每次垃圾收集時(shí)會(huì)把存活的對(duì)象整理到對(duì)應(yīng)可用的 Region 區(qū)域,再把原來的 Region 區(qū)域標(biāo)記為可回收區(qū)域并記錄到 Collect Set 中,因此 G1 的每一次回收都可以看作是一次標(biāo)記整理過程,兩者都不會(huì)產(chǎn)生空間碎片問題。

2.5.5、小結(jié)

總結(jié)下來,收集器特點(diǎn)如下:

  • 收集區(qū)域:整個(gè)堆內(nèi)存
  • 收集算法:復(fù)制算法
  • 收集方式:多線程
  • 優(yōu)勢(shì):停頓時(shí)間可控,吞吐量高,不會(huì)產(chǎn)生空間碎片,不需要額外的收集器搭配
  • 劣勢(shì):目前而言,相較于 CMS,G1 還不具備全方位、壓倒性優(yōu)勢(shì),G1 在收集過程中內(nèi)存占用和執(zhí)行負(fù)載都偏高;其次,在小內(nèi)存應(yīng)用上 CMS 的表現(xiàn)大概率會(huì)優(yōu)于 G1,而 G1 在大內(nèi)存應(yīng)用上會(huì)比較有優(yōu)勢(shì),6G 以上的內(nèi)存可以考慮使用 G1 收集器

2.6、常用的收集器組合

最后我們對(duì)以上介紹的垃圾收集器進(jìn)行一次匯總,同時(shí)介紹一下服務(wù)器端常用的組合模式,內(nèi)容如下。

服務(wù)器組合

新生代收集器

老年代收集器

備注

組合一

Serial

Serial Old

Serial 是一個(gè)使用單線程采用復(fù)制算法的新生代收集器;Serial Old 是一個(gè)使用單線程采用標(biāo)記整理算法的老年代收集器,GC 時(shí)會(huì)暫停所有應(yīng)用線程,可以使用-XX:+UseSerialGC選項(xiàng)來開啟

組合二

ParNew

Serial Old

ParNew 是一個(gè)使用多線程采用復(fù)制算法的新生代收集器,GC 時(shí)會(huì)暫停所有應(yīng)用線程,可以使用-XX:+UseParNewGC選項(xiàng)來開啟

組合三

Parallel Scavenge

Serial Old

Parallel Scavenge 是一個(gè)使用多線程采用復(fù)制算法的新生代收集器,GC 時(shí)會(huì)暫停所有應(yīng)用線程,可以使用-XX:+UseParallelGC選項(xiàng)來開啟;需要注意的是,在jdk1.7及之前的版本中,這個(gè)參數(shù)默認(rèn)采用 Serial Old 作為老年代收集器;在jdk1.8及之后的版本中,默認(rèn)采用 Parallel Old 作為老年代收集器

組合四

Parallel Scavenge

Parallel Old

Parallel Old是 Serial Old 的多線程版收集器,可以使用-XX:+UseParallelOldGC選項(xiàng)來開啟

組合五

Serial

CMS + Serial Old

CMS 是一個(gè)使用多線程采用標(biāo)記清楚算法的老年代收集器,可以實(shí)現(xiàn) GC 線程和用戶線程并發(fā)工作,不需要暫停所有用戶線程;另外,可以將 Serial Old 收集器作為備選,當(dāng) CMS 進(jìn)行 GC 失敗時(shí),會(huì)自動(dòng)使用 Serial Old 進(jìn)行 GC;可以使用-XX:+UseConcMarkSweepGC選項(xiàng)來開啟

組合六

ParNew

CMS + Serial Old

ParNew 是除了 Serial 以外,唯一一個(gè)能搭配 CMS 的新生代收集器;可以使用-XX:+UseConcMarkSweepGC開啟,默認(rèn)使用 ParNew 作為新生代收集器,也可以通過-XX:+UseParNewGC強(qiáng)制指定 ParNew

組合七

G1

G1

G1 是一個(gè)新一代的垃圾收集器,摒棄了原來的物理分區(qū),把整個(gè) Java 堆分成若干個(gè)大小相等的獨(dú)立區(qū)域(Region),針對(duì)局部區(qū)域使用多線程采用復(fù)制算法進(jìn)行篩選回收,可以使用-XX:+UseG1GC選項(xiàng)來開啟

03、方法區(qū)回收

以上介紹的都是對(duì)象的回收過程,在之前的 JVM 內(nèi)存結(jié)構(gòu)的文章中我們介紹到,Java 應(yīng)用程序運(yùn)行時(shí),除了堆空間會(huì)存在垃圾數(shù)據(jù)以外,方法區(qū)同樣也存在。

雖然虛擬機(jī)規(guī)范中沒有明確要求方法區(qū)一定要實(shí)現(xiàn)垃圾回收,主要原因在于這個(gè)區(qū)域的垃圾回收效率非常低,但是 HotSpot 虛擬機(jī)對(duì)方法區(qū)也會(huì)進(jìn)行回收的,主要回收的是廢棄常量和無用的類兩部分。

如何判斷一個(gè)常量是否為“廢棄常量”呢?其實(shí)很簡(jiǎn)單,只要當(dāng)前系統(tǒng)中沒有任何一處引用該常量,就會(huì)被判定為廢棄常量。

如何判斷一個(gè)類是否為“無用的類”呢?條件非??量?,需要同時(shí)滿足以下三點(diǎn)。

  • 1.該類所有實(shí)例都已經(jīng)被回收,也就是說 Java 堆中不存在該類的任何實(shí)例
  • 2.該類對(duì)應(yīng)的java.lang.Class對(duì)象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法
  • 3.加載該類的 ClassLoader 已經(jīng)被回收,也就是說這個(gè)類的類加載器被卸載回收了

滿足以上三個(gè)條件則表示這個(gè)類再也無用了,HotSpot 虛擬機(jī)會(huì)對(duì)此類進(jìn)行回收。例如在大量使用反射、動(dòng)態(tài)代理、CGLib 等 ByteCode 框架,并自定義 ClassLoader 創(chuàng)建的類,為了保證方法區(qū)不會(huì)溢出,虛擬機(jī)會(huì)在適當(dāng)?shù)那闆r下對(duì)無用的類進(jìn)行回收。

在 JDK1.7 及以前的版本中,用永久代來作為方法區(qū)的實(shí)現(xiàn),當(dāng)永久代的空間不足時(shí)會(huì)觸發(fā) Full GC。

在 JDK1.8 及之后的版本中,用元空間來作為方法區(qū)的實(shí)現(xiàn),元空間的內(nèi)存空間默認(rèn)使用的是操作系統(tǒng)的內(nèi)存空間,它的垃圾回收不再由 Java 來控制,元空間的內(nèi)存管理由元空間虛擬機(jī)來完成。

04、小結(jié)

本文主要圍繞對(duì)象的垃圾收集器,做了一次知識(shí)內(nèi)容的整理和總結(jié),如果有描述不當(dāng)?shù)牡胤?,歡迎大家留言指出,不勝感激。

05、參考

1.https://zhuanlan.zhihu.com/p/267223891

2.https://www.cnblogs.com/xrq730/p/4836700.html

3.https://zhuanlan.zhihu.com/p/248709769

4.http://www.ityouknow.com/jvm/2017/09/28/jvm-overview.html

責(zé)任編輯:武曉燕 來源: 潘志的研發(fā)筆記
相關(guān)推薦

2024-12-30 08:03:08

2017-09-21 14:40:06

jvm算法收集器

2022-04-19 11:25:31

JVMZGC垃圾收集器

2024-03-14 09:00:00

2011-12-20 10:43:21

Java

2023-08-27 21:29:43

JVMFullGC調(diào)優(yōu)

2011-07-21 14:54:26

java垃圾收集器

2022-07-25 10:15:29

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

2020-02-25 22:01:36

理解JVM垃圾收集器

2013-12-19 09:46:04

垃圾收集器

2024-08-09 08:41:14

2009-10-30 10:47:48

VB.NET垃圾收集器

2023-11-16 08:00:56

Java11G1

2024-03-15 08:04:30

G1CMSJVM

2024-03-27 10:27:35

延遲垃圾收集器

2011-05-10 16:04:45

Java垃圾收集器

2010-09-27 12:42:15

JVM1.4.1JVM垃圾收集

2024-09-18 13:57:15

2021-04-27 11:28:21

React.t事件元素

2025-04-28 01:22:45

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)