日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java常见GC算法_垃圾收集器及内存分配_G1垃圾收集器

發(fā)布時(shí)間:2024/7/5 java 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java常见GC算法_垃圾收集器及内存分配_G1垃圾收集器 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

常見GC算法

  • 引用計(jì)數(shù)法: 每個(gè)對(duì)象都有一個(gè)計(jì)數(shù)器, 對(duì)象被引用一次, 計(jì)數(shù)器+1, 當(dāng)對(duì)象引用失敗一次. 計(jì)數(shù)器-1, 當(dāng)對(duì)象計(jì)數(shù)器等于0, 說明對(duì)象沒有被應(yīng)用, 就可GC
優(yōu): 運(yùn)行過程中, 可隨時(shí)檢查對(duì)象計(jì)數(shù)器, 進(jìn)行GC, 且GC過程, 應(yīng)用無需暫停, 執(zhí)行速度快(單個(gè)對(duì)象GC不會(huì)影響其他對(duì)象), 內(nèi)存不足, OOM 缺: 存在循環(huán)引用問題(A引用B, B引用A, A=null, B=null. A,B永遠(yuǎn)不會(huì)GC), 隨時(shí)都在GC, 占用CPU
  • 標(biāo)記清除: 先標(biāo)記( 從root進(jìn)行可達(dá)性分析, 標(biāo)記被引用的對(duì)象), 再清除(清除那些沒被引用的對(duì)象)
優(yōu); 解決循環(huán)引用問題 缺: 效率低下, 需要遍歷所有對(duì)象, 碎片化嚴(yán)重, 清理出來的內(nèi)存不連續(xù), 當(dāng)new大對(duì)象時(shí), 容易爆OOM
  • 標(biāo)記壓縮: 標(biāo)記需要回收的區(qū)域, 進(jìn)行回收, 將碎片化的空間進(jìn)行壓縮
優(yōu): 解決標(biāo)記清除的碎片化問題 缺: 需要移動(dòng)內(nèi)存位置, 效率降低
  • 復(fù)制算法: 將空間一分為二(只使用其中一塊空間進(jìn)行存儲(chǔ)), 進(jìn)行清除的時(shí)候, 將存活對(duì)象復(fù)制到另外一塊空間, 原本的空間全部清除, 解決移動(dòng)內(nèi)存問題
優(yōu): 解決標(biāo)記清除存在的內(nèi)存移動(dòng)問題 缺: 對(duì)空間的浪費(fèi)較為嚴(yán)重, 不適用內(nèi)存空間垃圾較少的情況

復(fù)制算法在JVM年輕代的應(yīng)用

1. GC開始前, 對(duì)象分布于Eden, s0區(qū), s1區(qū)為空 2. GC開始, Eden中的存活對(duì)象全部復(fù)制到s1中, s0區(qū)中存活對(duì)象根據(jù)他們的年齡值決定去向使用-XX:MaxTenuringThreshold設(shè)置年齡閾值, 超過該閾值, s0中對(duì)象移到老年代, 未達(dá)到, 對(duì)象則移動(dòng)到s1中 3. GC完成, 清空Eden, s0區(qū)域, s0與s1交換角色, 重復(fù)步驟1, 直到"s1"被填滿, 然后將"s1"中對(duì)象全部移到老年代中 優(yōu): 垃圾對(duì)象較多時(shí), 效率高, 無碎片化 缺: 垃圾較少, 不適用, 如:老年代, s0/s1一個(gè)時(shí)刻只能使用其中一塊, 內(nèi)存使用率低

分代算法: 年輕代采用復(fù)制清除, 老年代使用標(biāo)記清除/壓縮

垃圾收集器及內(nèi)存分配

  • 串行垃圾收集器: GC過程, 只有一個(gè)線程工作, 且應(yīng)用要停止運(yùn)行(Stop-the-world), 等待GC完成.
/*** 測(cè)試GC收集器* @author regotto*/ public class GcTest {public static void main(String[] args) {ArrayList<Object> objects = new ArrayList<>();while (true) {if (System.currentTimeMillis() % 2 == 0) {//產(chǎn)生大量廢棄對(duì)象objects.clear();} else {for (int i = 0; i < 10000; i++) {Properties properties = new Properties();properties.put("key:" + i, "value:" + System.currentTimeMillis());objects.add(properties);}}try {Thread.sleep(new Random().nextInt(100));} catch (InterruptedException e) {e.printStackTrace();}}} }

設(shè)置VM Optional: 使用串行GC器, 打印GC細(xì)節(jié)

運(yùn)行結(jié)果如下:


日志解讀(使用第一行數(shù)據(jù)):

GC: 年輕代GC; Full GC: 所有空間全部GC DefNew: 使用串行GC器 4416k -> 512k(4928k): GC前年輕代對(duì)象占4416k空間, GC年輕代對(duì)象占512k空間, 總共4928k空間 0.0019950secs: GC花費(fèi)時(shí)間 7318k -> 3975k(15872k): 堆空間GC情況
  • 并行垃圾回收器: 在串行GC的基礎(chǔ)上, 變?yōu)槎嗑€程進(jìn)行GC操作(存在Stop-the-world), 其余與串行GC一樣
    • ParNew垃圾收集器
      只能在年輕代工作(只是將串行GC變?yōu)椴⑿蠫C), 使用-XX:+UseParNewGC設(shè)置, 老年代依舊采用串行GC

      測(cè)試代碼在上一個(gè)代碼的基礎(chǔ)上修改VM options
      運(yùn)行過程中, 發(fā)現(xiàn)相比于SerialGC, ParNew在GC上存在一定的提升
    • ParallelGC垃圾收集器
      與ParNew一樣, 新增多個(gè)與吞吐量相關(guān)的參數(shù), 操作更加靈活
-XX:+UseParallelGC 年輕代使用ParallelGC垃圾回收器,老年代使用串行回收器。 -XX:+UseParallelOldGC 年輕代使用ParallelGC垃圾回收器,老年代使用ParallelOldGC垃圾回收器。 -XX:MaxGCPauseMillis 設(shè)置最大的垃圾收集時(shí)的停頓時(shí)間,單位為毫秒 需要注意的是,ParallelGC為了達(dá)到設(shè)置的停頓時(shí)間,可能會(huì)調(diào)整堆大小或其他 的參數(shù),如果堆的大小設(shè)置的較小,就會(huì)導(dǎo)致GC工作變得很頻繁,反而可能會(huì) 影響到性能。 該參數(shù)使用需謹(jǐn)慎。 -XX:GCTimeRatio 設(shè)置垃圾回收時(shí)間占程序運(yùn)行時(shí)間的百分比,公式為1/(1+n)。 它的值為0~100之間的數(shù)字,默認(rèn)值為99,也就是垃圾回收時(shí)間不能超過1% -XX:UseAdaptiveSizePolicy 自適應(yīng)GC模式,垃圾回收器將自動(dòng)調(diào)整年輕代、老年代等參數(shù),達(dá)到吞吐量、 堆大小、停頓時(shí)間之間的平衡。 一般用于,手動(dòng)調(diào)整參數(shù)比較困難的場(chǎng)景,讓收集器自動(dòng)進(jìn)行調(diào)整。


測(cè)試代碼與前一個(gè)一樣, 只修改VM options, 運(yùn)行結(jié)果如下:

  • CMS垃圾處理器
    CMS(Concurrent Mark Sweep): 針對(duì)老年代(對(duì)老年代GC進(jìn)行改進(jìn)), 使用標(biāo)記清除算法, -XX:UseConcurrentMarkSweepGC設(shè)置.
    執(zhí)行過程如下:
InitialMarking: 標(biāo)記root, 出現(xiàn)Stop-the-world Marking: 標(biāo)記對(duì)象, 與應(yīng)用線程同時(shí)運(yùn)行 preclean: 預(yù)清理, 與應(yīng)用線程同時(shí)運(yùn)行 finalMarking: 再次標(biāo)記, 由于與應(yīng)用線程同時(shí)運(yùn)行, 前期的標(biāo)記并不能解決問題, 此過程出現(xiàn)Stop-the-world sweeping: 并發(fā)清除, 與應(yīng)用線程同時(shí)運(yùn)行 resizing: 調(diào)整堆大小, 清理碎片, 壓縮空間 resetting: 重置, 等待觸發(fā)下一次CMS, 與用戶線程同時(shí)運(yùn)行


程序打印的日志也是按照上面的流程, 程序運(yùn)行結(jié)果如下:

G1垃圾收集器(jdk1.7使用)

G1取消傳統(tǒng)的新生代, 老年代物理劃分, 將內(nèi)存空間變?yōu)槿舾蓚€(gè)區(qū)域, 每個(gè)區(qū)域包含邏輯上的新生代, 老年代. G1存在YoungGC, MixedGC, FullGC, 在不同的條件下觸發(fā)

優(yōu): 每一塊區(qū)域存在多種狀態(tài)(Old, Eden, Humongous, Survivor)解決碎片化問題, 即使在正常處理過程中, 都能解決內(nèi)存壓縮問題

G1的YoungGC

Eden區(qū)空間耗盡觸發(fā), EdenGC, Eden中數(shù)據(jù)移動(dòng)到Survivor區(qū)(Survivor滿了, 數(shù)據(jù)移動(dòng)到新的Survivor區(qū), 部分?jǐn)?shù)據(jù)移動(dòng)到Old區(qū)), 部分?jǐn)?shù)據(jù)移動(dòng)到Old區(qū), 當(dāng)前Eden清空, 變?yōu)槲词褂脜^(qū)

RememberSet(記憶集合)

RememberSet解決新生代尋找根對(duì)象的問題, 每一個(gè)區(qū)域初始化都生成一個(gè)RememberSet, 該集合保存其他對(duì)象引用"我"的記錄, 掃描RememberSet就能得出對(duì)象之間的引用關(guān)系, 而不再需要對(duì)新生代, 老年代中所有對(duì)象進(jìn)行掃描.

G1的MixedGC

為避免堆內(nèi)存被耗盡, JVM啟動(dòng)MixedGC, 回收所有的Young區(qū), 回收部分Old區(qū)(MixedGC不是FullGC).
使用-XX:InitiatingHeapOccupancyPercent=n(老年代占整個(gè)堆大小百分比閾值) 決定MixedGC什么時(shí)候觸發(fā)
MixedGC分為2個(gè)步驟: 全局并發(fā)標(biāo)記(前5個(gè)步驟), 拷貝存活對(duì)象(第6個(gè)步驟)

G1相關(guān)參數(shù)

-XX:+UseG1GC 使用 G1 垃圾收集器 -XX:MaxGCPauseMillis 設(shè)置期望達(dá)到的最大GC停頓時(shí)間指標(biāo)(JVM會(huì)盡力實(shí)現(xiàn),但不保證達(dá)到),默認(rèn) 值是 200 毫秒。 -XX:G1HeapRegionSize=n 設(shè)置的 G1 區(qū)域的大小。值是 2 的冪,范圍是 1 MB 到 32 MB 之間。目標(biāo)是根 據(jù)最小的 Java 堆大小劃分出約 2048 個(gè)區(qū)域。 默認(rèn)是堆內(nèi)存的1/2000。 -XX:ParallelGCThreads=n 設(shè)置 STW 工作線程數(shù)的值。將 n 的值設(shè)置為邏輯處理器的數(shù)量。n 的值與邏輯 處理器的數(shù)量相同,最多為 8。 -XX:ConcGCThreads=n 設(shè)置并行標(biāo)記的線程數(shù)。將 n 設(shè)置為并行垃圾回收線程數(shù) (ParallelGCThreads) 的 1/4 左右。 -XX:InitiatingHeapOccupancyPercent=n 設(shè)置觸發(fā)標(biāo)記周期的 Java 堆占用率閾值。默認(rèn)占用率是整個(gè) Java 堆的 45%。

G1日志輸出參數(shù)

‐XX:+PrintGC 輸出GC日志 ‐XX:+PrintGCDetails 輸出GC的詳細(xì)日志 ‐XX:+PrintGCTimeStamps 輸出GC的時(shí)間戳(以基準(zhǔn)時(shí)間的形式) ‐XX:+PrintGCDateStamps 輸出GC的時(shí)間戳(以日期的形式,如 2013‐05‐ 04T21:53:59.234+0800) ‐XX:+PrintHeapAtGC 在進(jìn)行GC的前后打印出堆的信息 ‐Xloggc:../logs/gc.log 日志文件的輸出路徑

測(cè)試


代碼運(yùn)行完畢自動(dòng)將GC日志輸入到項(xiàng)目下的gc.log中
使用GC Easy進(jìn)行分析(http://gceasy.io)
將gc.log上傳該網(wǎng)站, 就能進(jìn)行GC分析, 獲取分析報(bào)告

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的Java常见GC算法_垃圾收集器及内存分配_G1垃圾收集器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。