垃圾收集器–串行,并行,CMS,G1(以及Java 8中的新增功能)
4個Java垃圾收集器–錯誤的選擇如何嚴重影響性能
在2014年,對于大多數開發人員來說,還有兩件事仍然是個謎:垃圾收集和了解異性。 由于我對后者知之甚少,所以我認為我會對前者大吃一驚,特別是因為在該領域中,Java 8發生了一些重大變化和改進,尤其是去除了PermGen和一些新的令人興奮的優化(有關此方面的更多信息,請參見結尾)。
當我們談論垃圾收集時,我們中的絕大多數人都知道這個概念并將其應用于我們的日常編程中。 即使這樣,很多事情我們還是不了解,那時候情況就變得很痛苦。 關于JVM的最大誤解之一是它有一個垃圾收集器,實際上它提供了四種不同的垃圾收集器,每種垃圾都有其獨特的優缺點。 使用哪種選擇不是自動的,而是由您自己決定的,并且吞吐量和應用程序暫停之間的差異會很大。
這四種垃圾收集算法的共同點是它們是代生成的,這意味著它們使用古老的假設(即堆中的大多數對象是短壽命的,應Swift回收)將托管堆分成不同的段。 由于這也是一個覆蓋面廣的領域,因此,我將直接介紹不同的算法,以及它們的優缺點。
1.串行收集器
串行收集器是最簡單的一種,您可能不會使用,因為它主要是為單線程環境(例如32位或Windows)和小型堆而設計的。 該收集器會在其工作時凍結所有應用程序線程,這使它無法出于所有意圖和目的在服務器環境中使用。
使用方法:您可以通過打開-XX:+ UseSerialGC JVM參數來使用它,
2.并行/吞吐量收集器
接下來是并行收集器。 這是JVM的默認收集器。 就像它的名字一樣,它的最大優點是使用多個線程來掃描并壓縮堆。 并行收集器的不利之處在于,在執行次要或完全GC收集時,它將停止應用程序線程。 并行收集器最適合可以容忍應用程序暫停并試圖優化以減少由收集器引起的CPU開銷的應用程序。
3. CMS收集器
緊跟在并行收集器之后的是CMS收集器(“ current-mark-sweep ”)。 該算法使用多個線程(“并發”)在堆(“標記”)中進行掃描以查找可以回收(“清掃”)的未使用對象。 在兩種情況下,該算法將進入“世界停止”(STW)模式:初始化根的初始標記(從線程入口點或靜態變量可以訪問的舊代對象),并且應用程序更改了狀態在算法同時運行時將其堆放,迫使其返回并進行最后的修改以確保標記了正確的對象。
使用此收集器時,最大的問題是遇到升級失敗 ,這是在收集年輕一代和老一代之間出現種族狀況的情況。 如果收集器需要將年輕物體提升給老一代,但又沒有足夠的時間清理空間,則必須首先這樣做,這將導致完整的STW收集-這就是CMS收集器的初衷阻止。 為確保不會發生這種情況,您可以增加舊一代的大小(或為此增加整個堆的大小),或者為收集器分配更多的后臺線程,以供他與對象分配率競爭。
與并行收集器相比,此算法的另一個缺點是,它使用更多的CPU,以便通過使用多個線程來執行掃描和收集,從而為應用程序提供更高級別的連續吞吐量。 對于大多數長時間運行的服務器應用程序而言,這不利于應用程序凍結,這通常是一個不錯的選擇。 即使這樣, 默認情況下也不會啟用該算法。 您必須指定XX:+ USeParNewGC才能真正啟用它。 如果您愿意分配更多的CPU資源以避免應用程序暫停,那么這可能是您可能要使用的收集器,假設您的堆大小小于4Gb。 但是,如果大于4GB,則可能要使用最后一種算法-G1收集器。
4. G1收藏家
JDK 7更新4中引入的Garbage first收集器(G1)旨在更好地支持大于4GB的堆。 G1收集器利用多個后臺線程來掃描它劃分為多個區域的堆,范圍從1MB到32MB(取決于堆的大小)。 G1收集器旨在首先掃描那些包含最多垃圾對象的區域,并為其命名(垃圾優先)。 使用–XX:+ UseG1GC標志打開此收集器。
這種策略有可能在后臺線程完成掃描未使用的對象之前耗盡堆,在這種情況下,收集器將不得不停止應用程序,這將導致STW收集。 G1還具有另一個優勢,即它可以在移動過程中壓縮堆,這是CMS收集器僅在完整STW收集期間執行的操作。
在過去的幾年中,大堆一直是一個有爭議的領域,許多開發人員從每臺機器模型的單個JVM轉移到每臺機器具有多個JVM的更多微服務,組件化架構。 這是由許多因素驅動的,包括希望隔離不同的應用程序部分,簡化部署并避免通常將應用程序類重新加載到內存中所帶來的成本(在Java 8中已得到某些改進)。
即使這樣,涉及JVM的最大驅動程序之一還是希望避免大堆發生的長時間“停止世界”暫停(在大型集合中可能要花費幾秒鐘)。 Docker之類的容器技術也加快了這一步,使您能夠相對輕松地在同一臺物理計算機上部署多個應用程序。
Java 8和G1收集器
Java 8 update 20剛剛推出的另一個漂亮的優化是G1收集器字符串重復數據刪除 。 由于字符串(及其內部char []數組)占用了我們的大部分堆空間,因此進行了新的優化,使G1收集器可以識別在整個堆中重復多次的字符串,并更正它們以指向同一內部字符[]數組,以避免同一字符串的多個副本無效地駐留在堆中。 您可以使用-XX:+ UseStringDeduplication JVM參數來進行嘗試。
Java 8和PermGen
Java 8中最大的更改之一是刪除了堆中的permgen部分,該部分通常分配給類元數據,內部字符串和靜態變量。 傳統上,這要求開發人員使用的應用程序會加載大量的類(對于使用企業容器的應用程序很常見),以專門針對堆的這一部分進行優化和調整。 多年來,這已成為許多OutOfMemory異常的來源,因此(如果是非常不錯的)添加JVM(主要是)要多加注意。 即使這樣,它本身也可能不會減少開發人員將其應用程序分離到多個JVM中的浪潮。
這些收集器中的每一個都通過一系列的撥動開關進行不同的配置和調整,每一個都有增加或減少吞吐量的潛力,所有這些都取決于應用程序的特定行為。 在下一篇文章中,我們將探討配置這些策略的關鍵策略。
同時,您最想了解關于不同收藏家之間差異的哪些事情? 在評論部分打我!
補充閱讀
翻譯自: https://www.javacodegeeks.com/2014/09/garbage-collectors-serial-vs-parallel-vs-cms-vs-g1-and-whats-new-in-java-8.html
總結
以上是生活随笔為你收集整理的垃圾收集器–串行,并行,CMS,G1(以及Java 8中的新增功能)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ddos攻击需要多少肉鸡(ddos10g
- 下一篇: 二类医疗器械经营备案证(经营备案证)