成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

簡單聊聊JVM中的幾種垃圾收集算法

開發 前端
G1 收集器的垃圾回收流程和 CMS 邏輯大致相同,主要的區別在最后一個階段,G1 不會直接進行清除,而是會根據設置的停頓時間進行智能的篩選和局部的回收,采用“標記復制”算法來實現。
一、摘要

在之前的文章中,我們介紹了對象的創建過程,以及運行期的相關優化手段。本文主要介紹對象回收的判定方式以及垃圾對象的回收算法等相關知識。

下面我們一起來了解一下。

二、對象回收判定方式

當一個對象被創建時,虛擬機會優先分配到堆空間中,當對象不再被使用了,虛擬機會對其進行回收處理,以便釋放內存空間,這個過程也被稱為垃圾對象回收。

那么如何找到對象是否可以進行回收呢?一般有兩種方式。

引用計數法

可達性分析法

下面我們一起來了解下相關知識。

2.1、引用計數法

這個方法的實現思路是:在對象中維護一個引用計數器,每當一個地方引用這個對象時,計數器值+1;當引用失效時,計數器值-1。當對象的計數器值為 0,表示這個對象不再被使用了,可以被回收。

這種方法使用場景很多,但很少有垃圾收集器會使用這種方式。

原因在于:這種方式存在一個致命的缺陷,比如堆中的兩個對象相互引用,此時他們的計數器值是 1,但這兩個對象并沒有被外部使用,因此不會被回收,容易造成內存泄露。

2.2、可達性分析法

這個方法的實現思路是:從“GC Roots”(這個 GC Roots 可以是棧中的引用變量,也可以是方法區的引用變量或常量)開始掃描堆中的對象,沿著 GC Roots 一路掃描,被掃描的所有對象全部標記為存活對象;掃描完成之后,沒有被標記的視為垃圾對象,可以被回收。

比如對象 A 被線程占中的變量 a 引用著,對象 A 中引用著對象 B,對象 B 又引用著 C 等,沿著 a 開始掃描,會掃描到對象 A,B,C 等,并把它們標記為存活對象。全部掃描完成之后,當一個對象到 GC Roots 沒有任何引用鏈時,表示此對象是不可用的,等待被 GC 回收。

圖片圖片

在 JVM 中,可以作為 GC Roots 的對象包括:

  • 虛擬機棧中引用的對象
  • 方法區中靜態屬性引用的對象
  • 方法區中常量引用的對象
  • 本地方法棧中 JNI(即 Native 方法)引用的對象

三、垃圾回收算法

當一個對象被判定為垃圾對象之后,剩下的工作就是如何進行回收了。

下面我們一起來看看常見的幾種垃圾回收算法的思想。

3.1、標記-清除算法

標記-清除算法如同它的名字一樣,分為“標記”和“清除”兩個階段,也是最基礎的算法。

首先標記出所有需要回收的對象,標記完成后統一回收所有被標記的對象。之所以說它是最基礎的收集算法,是因為后續的收集算法都是基于這種思路并對其缺點進行改進而得到的。

這個算法也有很多的不足,主要體現在效率和空間。

  • 從效率的角度講,標記和清除兩個過程的效率都不高;
  • 從空間的角度講,標記清除后會產生大量不連續的內存碎片,空間碎片太多可能會導致后面的程序運行過程中分配較大對象時,無法找到足夠的連續內存而不得不提前觸發一次垃圾收集動作

標記-清除算法執行過程,可以用如下圖來概括:

圖片圖片

3.2、復制算法

復制算法是為了解決效率問題而出現的,它將可用的內存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活著的對象復制到另外一塊上面,然后再把已使用過的內存空間一次清理掉。

這樣每次只需要對整個半區進行內存回收,內存分配時也不需要考慮內存碎片等復雜情況,只需要移動指針,按照順序分配即可。

這個算法也有缺點,操作的時候內存會縮小為了原來的一半,代價很高;其次,持續復制長生存期的對象會導致回收效果不佳,效率較低。

一般的商用虛擬機會采用這種算法來回收新生代(也稱為年輕代)的對象,不過研究表明1:1的比例不是很科學,因此新生代的內存空間被細劃分為一塊較大的 Eden 空間和兩塊較小的 Survivor 空間,每次使用 Eden 和其中一塊 Survivor;每次回收時,將 Eden 和 Survivor 空間中還存活的對象一次性復制到另外一塊 Survivor 空間上,最后清理掉之前的 Eden 和 Survivor 空間。

HotSpot 虛擬機默認 Eden 和 Survivor 區的比例是8 : 1 : 1,期望每次回收后只有不到 10% 的對象存活,如果出現 Survivor 空間不夠用時,需要依賴老年代進行分配擔保。

復制算法執行過程,可以用如下圖來概括:

圖片圖片

3.3、標記-壓縮算法

在上面我們提到了復制算法的優點和缺點,針對對象存活率較高的場景,進行大量的復制操作時,效率很低下。如果不想浪費 50% 的空間,當對象 100% 存活時,那么需要有額外的空間進行分配擔保。

在 HotSpot 虛擬機中,堆空間劃分成兩個不同的區域:新生代和老年代,目的是為了更有效率的回收對象。新生代的對象存活率低,會優先被回收,如果多次執行依然沒有被回收,就會轉移到老年代。老年代都是不易被回收的對象,對象存活率高,因此一般不能直接選用復制算法。

根據老年代的特點,有人提出了另外一種標記-整理算法,也稱為標記-壓縮算法,過程與標記-清除算法一樣,不過不是直接對可回收對象進行清理,而是讓所有存活對象都向一端移動,然后直接清理掉邊界外的內存。

標記-整理算法執行過程,可以用如下圖來概括:

圖片圖片

3.4、分代收集算法

分代收集算法,可以看成以上內容的延伸。它的實現思路是根據對象的生命周期的不同,將內存劃分為幾塊,比如把堆空間劃分為新生代和老年代,然后根據各塊的特點采用最適當的收集算法。

在新生代中,存在大批對象死去、少量對象存活的特點,會采用“復制算法”,只需要付出少量存活對象的復制成本就可以完成垃圾對象收集,效率高;在老年代中,存在對象存活率高、沒有額外空間對它進行分配擔保的特點,會采用“標記-清理”或者“標記-整理”算法來進行回收。

可以用如下圖來概括堆內存的空間布局:

圖片圖片

四、垃圾收集器

如果說收集算法是內存回收的方法論,那么垃圾收集器就是內存回收的具體實現。

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

圖片圖片

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

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

在虛擬機中,沒有所謂的萬能收集器,只有根據具體的業務場景,選擇最合適的收集器。這也是為什么 HotSpot 實現了這么多收集器的原因。

下面我們一起來看看相關的具體實現。

4.1、Serial 和 Serial Old收集器

Serial 系列的垃圾收集器是 JVM 的第一款收集器,它的設計思路很簡單,在新生代,使用單線程采用復制算法進行收集對象;在老年代,使用單線程采用標記整理算法進行收集對象;垃圾收集的過程中會暫停用戶線程,直到垃圾收集完畢。

因為當時的硬件環境配置都不高,內存都是幾十兆,CPU 也都是單核的,不像現在這樣處處都是高并發的應用場景。限于當時的硬件資源和應用場景,這個收集器優勢很突出,簡單高效、消耗資源也很少。

唯一的不足在于,在用戶不可見的情況下要把用戶正常工作的線程全部停掉,這對很多應用比較難以接受。不過實際上到目前為止,Serial 收集器依然是虛擬機在 Client 模式下運行的默認新生代收集器,因為它簡單而高效。客戶端應用模型下,分配給虛擬機管理的內存一般來說不會很大,收集幾十兆甚至一兩百兆的新生代對象,停頓時間平均在幾十毫秒,只要不是頻繁收集,完全可以接受。

整個流程,可以用如下圖來概括。

圖片圖片

總結下來,收集器特點如下:

  • 收集區域: Serial(新生代),Serial Old(老年代)
  • 收集算法: Serial(復制算法),Serial Old(標記整理算法)
  • 收集方式:單線程
  • 優勢:簡單高效,內存資源占用少,單核 CPU 環境最佳選項
  • 劣勢:整個搜集過程需要停頓用戶線程,多核 CPU、大內存的環境,資源優勢無法發揮起來

4.2、ParNew收集器

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

能讓 ParNew 出名的一個核心因素是,它是除了 Serial 收集器外,目前唯一一個能與 CMS 收集器配合一起使用的新生代收集器,因為 CMS 優秀所以 ParNew 也出名了,有點類似碰上了大款的感覺,其中 CMS 收集器是一款幾乎可以認為有劃時代意義的垃圾收集器,下文我們再講。

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

整個流程,可以用如下圖來概括。

圖片圖片

總結下來,收集器特點如下:

  • 收集區域:新生代
  • 收集算法:復制算法
  • 收集方式:多線程
  • 優勢:多線程收集,多核 CPU 環境下效率要比 serial 高,新生代中,除了 Serial 收集器外目前唯一一個能與 CMS 配合的收集器
  • 劣勢:整個搜集過程需要停頓用戶線程

4.3、Parallel Scavenge 和 Parallel Old收集器

Parallel Scavenge 和 ParNew 收集器很類似,也是一款使用多線程采用復制算法的新生代收集器;Parallel Old 收集器是一款使用多線程采用標記整理算法的老年代收集器;垃圾收集過程中也會暫停用戶線程,直到整個垃圾收集過程結束。

不同的是,Parallel 收集器更關注系統的吞吐量,也被稱為“吞吐量優先收集器”。

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

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

另外,Parallel 收集器是虛擬機在 Server 模式下運行的默認垃圾收集器。

整個執行流程,跟 ParNew 收集器類似。

總結下來,收集器特點如下:

  • 收集區域:Parallel Scavenge(新生代),Parallel Old(老年代)
  • 收集算法:Parallel Scavenge(復制算法),Parallel Old(標記整理算法)
  • 收集方式:多線程
  • 優勢:多線程收集,多核 CPU 環境下效率要比 serial 高
  • 劣勢:整個搜集過程需要停頓用戶線程

4.4、CMS收集器

CMS 收集器是一種以獲取最短回收停頓時間為目標的老年代收集器。

與前面幾個收集器不同,它采用了一種全新的策略可以在垃圾回收過程中的某些階段用戶線程和垃圾回收線程一起工作,從而避免了因為長時間的垃圾回收而使用戶線程一直處于等待之中。

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

CMS 的英文全程是:Concurrent Mark-Sweep Collector,從名字上就能看出 CMS 收集器是基于“標記-清除”算法實現的,它的運作過程相對于前面幾種收集器來說要更復雜一些,整個過程分為如下 4 個步驟:

  • 初始標記
  • 并發標記
  • 重新標記
  • 并發清除

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

圖片圖片

4.4.1、階段一:初始標記

初始標記階段的工作主要是標記一下 GC Roots 能直接關聯到的對象,這個過程會短暫的停頓用戶線程,因為并不會對整個 GC Roots 的引用進行遍歷,因此速度很快。

4.4.2、階段二:并發標記

并發標記階段的工作主要是把階段一標記好的 GC Roots 對象進行深度的遍歷,找到所有與 GC Roots 關聯的對象并進行標記,這個過程會采用多線程的方式進行遍歷標記,因為非常耗時,CMS 考慮到為了盡量不停頓用戶線程,因此這個階段不會暫停用戶線程,也就是說,此時 JVM 會分配一些資源給用戶線程執行任務,通過這樣的方式減少用戶線程的停頓時間。

4.4.3、階段三:重新標記

重新標記階段的工作主要是修補階段二用戶線程運行期間產生新的垃圾對象,進行重新標記,同樣也是采用多線程方式進行,此階段數量不會很多,會短暫的停頓用戶線程,速度也很快。

4.4.4、階段四:并發清除

并發清除階段的工作主要是對那些被標記為可回收的對象進行清理,在一般情況下,并發清除階段是使用的是“標記-清除”算法,因為這個過程不會牽扯到對象的地址變更,所以 CMS 在并發清除階段是不需要停止用戶線程的,對象回收效率非常高。

與此同時,正因為并發清除階段用戶線程也可以同時運行,所以在用戶線程運行的過程中自然也會產生新的垃圾對象,這也就是導致 CMS 收集器會產生“浮動垃圾”的原因,此時也會產生很多的空間碎片,當空間碎片到達了一定程度時,此時 CMS 就會使用“標記-整理”算法來解決空間碎片的問題。

在上文的垃圾回收算法中我們有說到,“標記-整理”算法會將對象的位置進行挪動并更新對象的引用的指向地址,在這個過程中,如果用戶線程同時運行的話會產生并發問題,因此當 CMS 進行碎片整理的時候必須得停止用戶線程。所以,在某些情況下,并發清除階段 CMS 也會停頓用戶線程。

CMS 收集器作為一個全新思路的垃圾收集器,雖然很優秀,但一直沒有被 Hospot 虛擬機納入為默認的垃圾收集器。時至今日,JDK1.8 使用的默認收集器都還是 Parallel scavenge 和 Parallel old 收集器,主要原因在于 CMS 存在一些比較頭疼的問題,比如浮動垃圾、空間碎片整理時會造成系統卡頓、在并發清除階段可能會出現系統長時間的假死。

4.4.5、小結

總結下來,收集器特點如下:

  • 收集區域:老年代
  • 收集算法:標記清除算法 + 標記整理算法
  • 收集方式:多線程
  • 優勢:多線程收集過程中可以做到不停止用戶線程,以獲取最短回收停頓時間
  • 劣勢:會產生浮動垃圾、空間碎片整理時會造成系統卡頓、并發清除階段可能會出現系統假死等問題

4.5、G1收集器

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

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

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

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

圖片圖片

在 G1 收集器里面維護了一個 Collect Set 集合,這個集合里面記錄了待回收的 Region 區域信息,同時也包括了每個 Region 區域可回收的大小空間。通過 Collect Set 里面的信息,G1 在進行垃圾收集時,可以根據用戶設定的可接受停頓時間來進行分析,在設定的時間范圍內優先收集垃圾最多的 Region 區域,以實現高吞吐、低停頓的收集效果。

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

  • 初始標記
  • 并發標記
  • 重新標記
  • 篩選回收

G1 收集器的垃圾回收流程和 CMS 邏輯大致相同,主要的區別在最后一個階段,G1 不會直接進行清除,而是會根據設置的停頓時間進行智能的篩選和局部的回收,采用“標記復制”算法來實現。

整個流程,可以用如下圖來概括。

圖片圖片

4.5.1、階段一:初始標記

此階段的工作內容與上文介紹的 CMS 收集器一樣,會先把所有 GC Roots 直接引用的對象進行標記,同時會短暫的停止用戶線程,因為不會對整個 GC Roots 的引用進行遍歷,因此速度比較快。

4.5.2、階段二:并發標記

此階段的工作內容與上文介紹的 CMS 收集器也一樣,找到所有與 GC Roots 關聯的對象并進行深度遍歷標記,會采用多線程的方式進行遍歷標記,因為比較耗時,為了盡量不停頓用戶線程,這個階段 GC 線程會和用戶線程同時運行,通過這樣的方式減少用戶線程的停頓時間。

4.5.3、階段三:重新標記

此階段的工作內容與上文介紹的 CMS 收集器也是一樣,針對階段二用戶線程運行的過程中產生新的垃圾,采用多線程方式進行重新標記,為了避免這個過程再次產生新的垃圾對象,會短暫的停止用戶線程,因為數量不會很多,因此速度比較快。

4.5.4、階段四:篩選回收

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

從局部來看,G1 使用的是復制算法,將存活對象從一個 Region 區域復制到另一個 Region 空閑區域;但從整個堆來看,G1 使用的邏輯又相當于標記整理算法,每次垃圾收集時會把存活的對象整理到對應可用的 Region 區域,再把原來的 Region 區域標記為可回收區域并記錄到 Collect Set 中,因此 G1 的每一次回收都可以看作是一次標記整理過程,兩者都不會產生空間碎片問題。

4.5.5、小結

總結下來,收集器特點如下:

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

4.6、常用的收集器組合

最后我們對以上介紹的垃圾收集器進行一次匯總,同時介紹一下服務器端常用的組合模式,內容如下。

服務器組合

新生代收集器

老年代收集器

備注

組合一

Serial

Serial Old

Serial 是一個使用單線程采用復制算法的新生代收集器;Serial Old 是一個使用單線程采用標記整理算法的老年代收集器,GC 時會暫停所有應用線程,可以使用-XX:+UseSerialGC選項來開啟

組合二

ParNew

Serial Old

ParNew 是一個使用多線程采用復制算法的新生代收集器,GC 時會暫停所有應用線程,可以使用-XX:+UseParNewGC選項來開啟

組合三

Parallel Scavenge

Serial Old

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

組合四

Parallel Scavenge

Parallel Old

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

組合五

Serial

CMS + Serial Old

CMS 是一個使用多線程采用標記清楚算法的老年代收集器,可以實現 GC 線程和用戶線程并發工作,不需要暫停所有用戶線程;另外,可以將 Serial Old 收集器作為備選,當 CMS 進行 GC 失敗時,會自動使用 Serial Old 進行 GC;可以使用-XX:+UseConcMarkSweepGC選項來開啟

組合六

ParNew

CMS + Serial Old

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

組合七

G1

G1

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

五、方法區回收

以上介紹的都是對象的回收過程,在之前的 JVM 內存結構的文章中我們介紹到,Java 應用程序運行時,除了堆空間會存在垃圾數據以外,方法區同樣也存在。

雖然虛擬機規范中沒有明確要求方法區一定要實現垃圾回收,主要原因在于這個區域的垃圾回收效率非常低,但是 HotSpot 虛擬機對方法區也會進行回收的,主要回收的是廢棄常量和無用的類兩部分。

如何判斷一個常量是否為“廢棄常量”呢?其實很簡單,只要當前系統中沒有任何一處引用該常量,就會被判定為廢棄常量。

如何判斷一個類是否為“無用的類”呢?條件非常苛刻,需要同時滿足以下三點。

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

滿足以上三個條件則表示這個類再也無用了,HotSpot 虛擬機會對此類進行回收。例如在大量使用反射、動態代理、CGLib 等 ByteCode 框架,并自定義 ClassLoader 創建的類,為了保證方法區不會溢出,虛擬機會在適當的情況下對無用的類進行回收。

在 JDK1.7 及以前的版本中,用永久代來作為方法區的實現,當永久代的空間不足時會觸發 Full GC。

在 JDK1.8 及之后的版本中,用元空間來作為方法區的實現,元空間的內存空間默認使用的是操作系統的內存空間,它的垃圾回收不再由 Java 來控制,元空間的內存管理由元空間虛擬機來完成。

六、小結

本文主要圍繞對象的回收判斷方式,垃圾回收算法以及垃圾收集器,做了一次知識內容的整理和總結,如果有描述不當的地方,歡迎大家留言指出,不勝感激。

七、參考

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

責任編輯:武曉燕 來源: Java極客技術
相關推薦

2024-12-30 08:03:08

2017-09-21 14:40:06

jvm算法收集器

2010-09-27 12:42:15

JVM1.4.1JVM垃圾收集

2022-05-06 22:13:56

JVM垃圾收集算法

2009-06-15 16:14:40

Java垃圾收集算法GC

2024-08-26 08:58:50

2010-02-22 08:58:35

JVM內存模型垃圾收集

2009-12-25 16:15:31

JVM垃圾回收算法

2022-03-21 11:33:11

JVM垃圾回收器垃圾回收算法

2017-08-04 10:53:30

回收算法JVM垃圾回收器

2022-01-20 10:34:49

JVM垃圾回收算法

2024-07-15 08:00:00

2010-01-06 16:33:50

.Net Framew

2025-01-06 08:22:41

2024-10-15 08:37:08

2018-04-10 10:49:17

負載均衡算法服務器

2022-06-10 07:13:29

JVM垃圾回收

2021-11-05 15:23:20

JVM回收算法

2012-01-09 16:53:36

JavaJVM

2022-04-19 11:25:31

JVMZGC垃圾收集器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 高清人人天天夜夜曰狠狠狠狠 | 国产成人精品免费视频大全最热 | 国产成人在线视频免费观看 | 99精品免费视频 | 国产精品区一区二 | 黄网站色大毛片 | 中文字幕亚洲免费 | 91高清在线观看 | 中文字幕av免费 | aaa综合国产 | 日韩精品一区二区三区中文在线 | 亚洲日韩欧美一区二区在线 | 999观看免费高清www | 欧美一级久久久猛烈a大片 日韩av免费在线观看 | 综合精品 | 一区二区三区视频 | 久久精品国产清自在天天线 | 国产精品久久久久久久久久久久 | 亚洲女人天堂成人av在线 | 日韩在线视频网址 | 亚洲性视频 | 亚洲国产成人精品女人久久久 | 久久精品国产一区二区电影 | 在线日韩视频 | 国产高清一区二区三区 | 国产精品一区二区电影 | 日韩一区二区av | 日韩欧美在线观看 | 中文字幕不卡视频在线观看 | 久久精品无码一区二区三区 | 亚洲视频在线观看 | 午夜三区| 一区二区小视频 | 日韩精品久久 | 综合久久av | 婷婷成人在线 | 欧美性视频在线播放 | 日本一区二区三区精品视频 | 一级黄色毛片 | 国产高清免费 | 三级在线观看 |