關於Java垃圾回收,你必須要知道FullGC是什麼

2020-12-08 居家程式設計師

本文共3198字,是本人前幾天面試被提問到的一個問題,將在該文中闡述關於Java垃圾回收——Full GC的相關知識,包括定義、觸發條件、具體過程。

前幾天面試的時候,面試官在最後問了我一個有關Full GC的垃圾回收問題,希望我說明下該GC的定義、以及是如何觸發的問題,有感便記下這篇文章。

垃圾回收的定義

首先我們要知道GC這個概念,即就是我們常說的Java垃圾回收機制,Java通過可達性分析一個對象的引用是否存在,當不存在的時候,將回收堆中的對象。

目前主流的JVM,也就是HotSpot,採用的是分代收集算法。分代的含義涉及到Java的運行時數據區域,在下面幾個環節我們來簡單描述下Java的內存結構、FullGC的觸發以及分代收集算法是對應的哪些內存區域。

垃圾回收相關基礎知識

一般而言,GC主要是針對運行的數據區的。作為程式設計師要關注的區域主要有5塊,分別是方法區(Method Area),Java棧(Java stack),本地方法棧(Native Method Stack),堆(Heap),程序計數器(Program Counter Register)。實際jvm在管理內存的時候,比這個分的更細緻,只不過做應用程式開發,我們只需要關注這5塊就可以了。

可以關注到,其中有一個區域叫做「堆」,也就是Heap了,它是Jvm管理的內存中最大的一塊。程序的主要數據也都是存放在堆內存中的,也就是說程序所創建的對象基本上都在該區域進行內存分配,這一塊區域被所有的線程所共享,通常出現線程安全問題的一般都是這個區域的數據出現的問題。通常我們所說的gc主要是針對java heap這塊區域的。下面來了解一下heap區。

可見,Heap區在設計上是分代設計的,其劃分為了Eden、Survivor 和 Tenured/Old ,其中Eden區、Survivor(存活)屬於年輕代,Tenured/Old區屬於老年代或者持久代。

一般我們將年輕代發生的GC稱為Minor GC,對老年代進行GC稱為Major GC。

而本文所要闡述的FullGC是對整個堆來說的,在最近幾個版本的JDK裡默認包括了對永生帶即方法區的回收(JDK8中無永生帶了),出現Full GC的時候經常伴隨至少一次的Minor GC,但非絕對的。Major GC的速度一般會比Minor GC慢10倍以上。

到這裡,可能會有些人對heap分區的意義不太理解,我們在這裡就簡單介紹下年輕代和老年代是如何進行工作的,我們需要知道關於JVM的堆區對象分配的一般規則:

1. 對象優先在Eden區分配

2. 大對象直接進入老年代(-XX:PretenureSizeThreshold=3145728 這個參數來定義多大的對象直接進入老年代)

3. 長期存活的對象將進入老年代(在JDK8中測試,-XX:MaxTenuringThreshold=1的閥值設定根本沒用)

4. 動態對象年齡判定(虛擬機並不會永遠地要求對象的年齡都必須達到MaxTenuringThreshold才能晉升老年代,如果Survivor空間中相同年齡的所有對象的大小總和大於Survivor的一半,年齡大於或等於該年齡的對象就可以直接進入老年代)

5. 空間分配擔保

6. 只要老年代的連續空間大於(新生代所有對象的總大小或者歷次晉升的平均大小)就會進行minor GC,否則會進行full GC。

FullGC的觸發條件

在了解了關於GC的一些相關知識後,我們需要知道FullGC的觸發條件(這個是主要提問到點)。

上個環節我們知道了,FullGC是針對整個Heap區而言的,它將在以下幾種情況被觸發:

在程序中調用了System.gc()方法。此方法的調用是建議JVM進行Full GC,雖然只是建議而非一定,但很多情況下它會觸發 Full GC,從而增加Full GC的頻率,也即增加了間歇性停頓的次數。強烈影響系建議能不使用此方法就別使用,讓虛擬機自己去管理它的內存,可通過通過-XX:+ DisableExplicitGC來禁止RMI(Java遠程方法調用)調用System.gc。老年代空間不足。老年代空間只有在新生代對象轉入及創建為大對象、大數組時才會出現不足的現象,當執行Full GC後空間仍然不足,則拋出如下錯誤【java.lang.OutOfMemoryError: Java heap space】,而為避免以上兩種狀況引起的Full GC,調優時應儘量做到讓對象在Minor GC階段被回收、讓對象在新生代多存活一段時間及不要創建過大的對象及數組。Permanet Generation空間滿了。也就是以前所說的方法區,Permanet Generation中存放的為一些class的信息等,當系統中要加載的類、反射的類和調用的方法較多時,Permanet Generation可能會被佔滿,在未配置為採用CMS GC的情況下會執行Full GC。如果經過Full GC仍然回收不了,那麼JVM會拋出錯誤信息:java.lang.OutOfMemoryError: PermGen space 。為避免Perm Gen佔滿造成Full GC現象,可採用的方法為增大Perm Gen空間或轉為使用CMS GC。通過Minor GC後進入老年代的平均大小大於老年代的可用內存。如果發現統計數據說之前Minor GC的平均晉升大小比目前old gen剩餘的空間大,則不會觸發Minor GC而是轉為觸發full GC。由Eden區、From Space區向To Space區複製時,對象大小大於To Space可用內存,則把該對象轉存到老年代,且老年代的可用內存小於該對象大小。分配很大的對象。所謂大對象,是指需要大量連續內存空間的java對象,例如很長的數組,此種對象會直接進入老年代,而老年代雖然有很大的剩餘空間,但是無法找到足夠大的連續空間來分配給當前對象,此種情況就會觸發JVM進行Full GC。為了解決這個問題,CMS垃圾收集器提供了一個可配置的參數,即-XX:+UseCMSCompactAtFullCollection開關參數,用於在「享受」完Full GC服務之後額外免費贈送一個碎片整理的過程,內存整理的過程無法並發的,空間碎片問題沒有了,但停頓時間不得不變長了,JVM設計者們還提供了另外一個參數 -XX:CMSFullGCsBeforeCompaction,這個參數用於設置在執行多少次不壓縮的Full GC後,跟著來一次帶壓縮的。常見的垃圾回收器——回收過程

垃圾回收器並不是本文的主題,但還是想簡單列舉一下:

Serial收集器ParNew收集器Parallel Scavenge收集器CMS(Concurrent Mark Sweep)收集器G1(Garbage First)收集器(從JDK1.7 Update 14之後的HotSpot虛擬機正式提供了商用的G1收集器)

不知道各位還好不好奇上上個環節說到的分代收集算法。

大致我們也能猜到,其實就是針對年輕代和老年代,JVM將使用不同的垃圾收集算法進行收集,達到高效的垃圾回收。

年輕代採用的是標記-複製算法,將需要回收的對象標記,將不需要的對象移動到Survivor空間,然後將標記對象回收,該算法可以實現對大多數會失效的對象進行回收,對少部分不需要回收的對象進行轉移,保證eden區擁有連續的內存空間,而且複製的效率高。

因為在年輕代不需要回收的對象一般是很少的,每次垃圾收集時都有大批對象死去,只有少量存活,選用複製算法,只需要付出少量存活對象的複製成本就可以完成收集。

老年代採用的是標記-整理算法,將需要回收的對象標記,將不需要的對象進行移動整理,使不需要回收的對象佔用連續的內存空間,再清除回收對象,保證老年代擁有連續的內存空間,而且整理效率高。

因為在老年代需要回收的對象一般是很少的,其存活率較高、沒有額外空間對它進行分配擔保。

相關焦點

  • java垃圾回收以及jvm參數調優概述
    本文從基礎的理論入手,結合作者在實際項目中的實際使用來闡述JVM的垃圾回收機制以及如何對JVM進行調優。建議可以保存下來慢慢看,或者找一段安靜的時間全片通讀。關於作者,想必solr中國的小夥伴都不會陌生,這這裡就不做過多的介紹了。本文共分為五個部分,詳細闡述JAVA的垃圾回收以及JVM的參數調優。
  • 關於有害垃圾,你必須知道……
    關於有害垃圾,你必須知道…… 2020-05-26 02:16 來源:澎湃新聞·澎湃號·政務
  • 大型企業JVM性能調優實戰Java垃圾收集器及gcroot
    疑問:什麼是核心類 1:其實就是我們每天在開發的使用java.lang,java.util,等這些包下的類。而這個類都是存放在 jre/lib/rt.jar 中查看某個類:項目整個加載和過程是什麼樣子的。
  • java面試題總結:java的接口類和抽象類的特點
    Constructor不能被繼承,所以Constructor也就不能被override,但是可以overload  java垃圾回收的優點和原理,寫出兩種垃圾回收可調用的方法 java垃圾回收的優點:它使得Java程式設計師在編寫程序的時候不再需要考慮內存管理
  • Java垃圾回收機制(GC)—怎麼回收垃圾(內存)?
    Java垃圾回收機制提供了一些算法來回收垃圾對象內存:Tracing算法(Tracing Collector)或標記-清除算法標記-清除算法是最基礎的收集算法,為了解決引用計數法的問題而提出的。它使用了根集的概念,它分為「標記」和「清除」兩個階段:首先標記出所需回收的對象,在標記完成後統一回收掉所有被標記的對象,它的標記過程其實就是對前面的根搜索算法中判定垃圾對象的標記過程。優點:不需要進行對象的移動,並且僅對不存活的對象進行處理,在存活對象比較多的情況極為有效。
  • Java面試寶典---Java基礎部分(7)
    如果對象要保存在HashSet或HashMap中,它們的equals相等,那麼,它們的hashcode值就必須相等。如果不是要保存在HashSet或HashMap,則與hashcode沒有什麼關係了,這時候hashcode不等是可以的,例如arrayList存儲的對象就不用實現hashcode,當然,我們沒有理由不實現,通常都會去實現的。
  • java中為什麼不推薦使用finalize,知道原因後相信你也不會用了
    java提供了一個finalize方法,可以幫助我們進行資源釋放,類似於C++中的析構函數。但是目前普遍的認識是不要使用,為什麼呢?就是因為對java虛擬機的垃圾回收有影響。這篇文章對其進行一個說明。一、為什麼有影響我們都知道一個對象如果沒有了任何引用,java虛擬機就認為這個對象沒什麼用了,就會對其進行垃圾回收,但是如果這個對象包含了finalize函數,性質就不一樣了。怎麼不一樣了呢?
  • 科普|垃圾分類:「你是什麼垃圾?」
    為推動張家界市公共機構生活垃圾分類工作,根據張家界市城市管理委員會《關於印發(張家界市生活垃圾分類工作實施方案)的通知》(張城委[2020]8號)文件精神。2020年12月底,市級公共機構基本實施生活垃圾強制分類。張小團知識科普,乾貨滿滿的垃圾分類攻略來咯!
  • 可回收垃圾真的被回收利用了嗎?
    我們扔進「可回收物」垃圾桶裡的東西真的被回收利用了嗎?當垃圾車把你丟棄的可回收垃圾運走後,你可能會突然想到一個可怕的問題:這些東西會被運到哪裡去?它們真的會被回收利用嗎?1973年,大學城成為美國第一個開展舊報紙循環利用的城市。到2006年,全美國有大約8660個路邊回收站。一開始,人們必須將垃圾分類。
  • 淺析java內存管理機制
    中,內存管理由JVM完全負責,java中的「垃圾回收器」負責自動回收無用對象佔據的內存資源,這樣可以大大減少程序猿在內存管理上花費的時間,可以更集中於業務邏輯和具體功能實現;但這並不是說java有了垃圾回收器程序猿就可以高枕無憂,將內存管理拋之腦外了!
  • 有害垃圾你了解多少?這些你必須知道……
    隨著社會經濟發展,人們生活水平不斷提升,日常生活中產生的垃圾也與日俱增。環境汙染現象也愈發嚴重。對生活垃圾回收利用勢在必行,這樣不僅保護環境,還節約了資源。因為垃圾種類繁多,它們被自然界消化分解的時間也有不同。處理方式稍有不當,就會對環境造成極大危害。那麼,我們應該怎麼處理呢?
  • 全國46城市垃圾要強制分類!美術生,你是什麼垃圾?
    大家都知道上海開始強制實行垃圾分類。「你是什麼垃圾?」誰能想到,這直擊靈魂深處的拷問,有一天竟成了上海朋友的日常。不過你別忙著嘲笑他們,因為這事很快輪到你,不久後,全國46個重點城市,統統要跑步進入垃圾分類「強制時代」。這46個城市分別是:快看看有沒有你的城市!捫心自問:這到底是什麼垃圾?
  • Java基礎面試題簡單總結
    java編譯器要求方法必須聲明拋出可能發生的非運行時異常,但是並不要求必須聲明拋出未被捕獲的運行時異常。所有的異常都是java.lang.Thowable的子類。43、垃圾回收的優點和原理。垃圾回收可以有效的防止內存洩露,有效的使用可以使用的內存。垃圾回收器通常是作為一個單獨的低級別的線程運行,不可預知的情況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清楚和回收, 程式設計師不能實時的調用垃圾回收器對某個對象或所有對象進行垃圾回收。回收機制有分代複製垃圾回收和標記垃圾回收,增量垃圾回收。
  • 電子垃圾回收
    這次電子垃圾回收意識調查表共設12個問題和被調查者個人的基本信息。1、你知道我市有「電子垃圾」的回收部門嗎?不知道的佔98%; 知道的佔2%。而這2%的知道者是在陽光數碼港啟動回收現場發放的調查表中體現的。
  • 關於 Java 序列化你不知道的 5 件事
    團隊感到陷入僵局,但這只是因為他們不知道關於 Java 序列化的一個重要事實:Java 序列化允許隨著時間的推移而改變類型。當我向他們展示如何自動進行序列化替換後,他們終於按計劃完成了向 HashMap 的轉變。本文是本系列的第一篇文章,這個系列專門揭示關於 Java 平臺的一些有用的小知識 — 這些小知識不易理解,但對於解決 Java 編程挑戰遲早有用。
  • 垃圾回收原來是這麼回事
    GC的定義因為我們期望讓內存管理變得自動(只管用內存,不管內存的回收),我們就必須做兩件事情: > 1. 找到內存空間裡的垃圾 > 2. 回收垃圾,讓程式設計師能再次利用這部分空間 [1] 只要滿足這兩項功能的程序,就是GC,不論它是在JVM中,還是在Ruby的VM中。
  • 垃圾回收站垃圾製成兒童玩具 味道大有毒
    記者甚至還發現竟有很多使用過的一次性注射器、輸液管、藥瓶等醫療垃圾。  回收站負責人:這都是從醫院收回來的,不是醫院收回來的哪有這麼多廢品(醫療廢物)。  解說:我國法律明令禁止醫療垃圾回流社會,必須按規定進行銷毀。因為醫療垃圾中的病原微生物容易造成傳染性疾病,所含致病細菌及病毒是普通生活垃圾的幾十倍甚至上千倍。回收站的負責人卻說,這些塑料醫療垃圾可是本地的搶手貨。
  • 仲愷廢舊二手設備回收你必須要知道的
    仲愷廢舊二手設備回收你必須要知道的   惠州市高標再生資源有限公司主要經營再生資源回收、加工(不含固體廢物、危險廢物、報廢汽車等需經相關批准的項目);固體廢物治理;船舶拆除;加工:金屬製品、建築材料等。如有需要,歡迎隨時來電諮詢!
  • JAVA經典面試題及答案(上)
    Java 虛擬機讓這個變為可能,因為它知道底層硬體平臺的指令長度和其特性。 2、JDK和JRE的區別是什麼?JDK是java的軟體開發包,jre是運行java程序的java虛擬機3、「static」關鍵字是什麼意思?
  • 你知道嗎?垃圾要分類,垃圾處理的增值稅也要分類~
    垃圾要分類 綠色/環保/節約 垃圾處理的 增值稅 也要分類