小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

CMS垃圾回收器詳解

 碼農(nóng)9527 2021-12-16

 Concurrent Mark Sweep??疵志椭?,CMS是一款并發(fā)、使用標(biāo)記-清除算法的gc。CMS是針對老年代進(jìn)行回收的GC。

CMS垃圾回收器詳解

  一、哪些對象可以回收

  1、引用計(jì)數(shù)法

  算法過程:

  每個(gè)對象有一個(gè)引用計(jì)數(shù)器,當(dāng)對象被引用一次計(jì)數(shù)器就加一,引用失效就減一,對于計(jì)數(shù)器為0的對象表示為垃圾對象,可以被GC回收。

  請分析以下哪些操作是原子性操作:

  缺點(diǎn):

  無法解決循環(huán)引用的問題,例如:A引用了B,B引用了A,但是A和B都沒有被其他對象引用,這樣就會導(dǎo)致內(nèi)存泄漏,無法被回收。

  2、可達(dá)性分析法

  算法過程:通過一系列被稱為GC Roots的對象作為起點(diǎn)開始搜索,所經(jīng)過的路徑被稱為引用鏈,當(dāng)一個(gè)對象沒有跟任何一個(gè)引用鏈相連接的時(shí)候,表示從GC Roots對象到這個(gè)對象不可達(dá),意味著這是一個(gè)垃圾對象可以被回收。

  適用場景:Java虛擬機(jī)是采用這種算法對垃圾進(jìn)行回收,解決了循環(huán)引用的問題。

  可以作為GC Roots對象有:虛擬機(jī)棧,靜態(tài)成員,常量,本地方法棧引用的對象。

  二、垃圾回收算法

  1、標(biāo)記清除

  算法過程:首先標(biāo)記出需要回收的對象,標(biāo)記完成后統(tǒng)一回收。

  缺點(diǎn):主要有兩個(gè)缺點(diǎn),一個(gè)是標(biāo)記和清除兩個(gè)過程的效率都不算高(據(jù)資料顯示)。另一個(gè)是空間問題,標(biāo)記清除后,會產(chǎn)生不連續(xù)的內(nèi)存碎片,當(dāng)需要分配大對象時(shí),無法找到足夠連續(xù)的內(nèi)存,導(dǎo)致分配失敗提前觸發(fā)GC。

  2、復(fù)制算法

  算法過程:將內(nèi)存分為兩部分,每次只使用其中一塊內(nèi)存?;厥諘r(shí)將存活的對象復(fù)制到另一塊區(qū)域,之后將已使用的內(nèi)存區(qū)域一次性全部清理掉。

  優(yōu)點(diǎn):解決了空間碎片的問題,存活對象少時(shí),提升了回收效率。

  缺點(diǎn):一個(gè)是內(nèi)存使用率縮小了,因?yàn)橛肋h(yuǎn)有一塊空閑的內(nèi)存?zhèn)溆?。另一個(gè)是當(dāng)存活對象較多時(shí)復(fù)制效率低下。

  3、標(biāo)記整理

  算法過程:標(biāo)記整理的算法過程跟標(biāo)記清除的標(biāo)記過程是一樣的,但標(biāo)記后是將存活的對象都向某一端移動,然后清理邊界以外的內(nèi)存。

  優(yōu)點(diǎn):解決了內(nèi)存碎片的問題。

  可以作為GC Roots對象有:虛擬機(jī)棧,靜態(tài)成員,常量,本地方法棧引用的對象。

  三、CMS介紹

  1、介紹

  老年代收集器,需要配合Serial或者ParNew使用,一般是與ParNew使用。CMS全稱Concurrent Mark-Sweep。CMS出現(xiàn)的目標(biāo)是為了降低延遲,減少回收停頓時(shí)間。適合對延遲、停頓時(shí)間敏感的應(yīng)用使用。通過 -XX:+UseConcMarkSweepGC開啟。

  2、回收階段

  CMS-initial-mark(STW):通過可達(dá)性分析算法,從GC Roots對象開始掃描能夠直接關(guān)聯(lián)到的對象,并做標(biāo)記,需要STW,但是一般會很快完成。

  CMS-concurrent-mark:從初始標(biāo)記的基礎(chǔ)上,繼續(xù)向下搜索并做標(biāo)記,這個(gè)階段應(yīng)用線程和GC線程并發(fā)執(zhí)行,不會造成停頓。

  CMS-concurrent-preclean:查找并發(fā)標(biāo)記階段中,新進(jìn)入老年代的對象,包括晉升到老年代和直接在老年代分配的對象,目的是減少下一個(gè)階段重新標(biāo)記的時(shí)間。

  CMS-concurrent-abortable-preclean:可中斷的預(yù)清理,這個(gè)階段做的事情跟并發(fā)預(yù)清理的事情一樣,目的是為了減少下一個(gè)階段STW的時(shí)間,這個(gè)階段有幾個(gè)個(gè)條件控制何時(shí)結(jié)束。

  A、-XX:CMSScheduleRemarkEdenSizeThreshold=2.該階段在Eden區(qū)占用超過2M時(shí)啟動。

  B、-XX:CMSMaxAbortablePrecleanTime=5000.設(shè)置一個(gè)最大時(shí)間最大執(zhí)行5秒鐘。

  C、-XX:CMSScheduleRemarkEdenPenetration=50.Eden區(qū)使用率超過50就停止該階段進(jìn)入remark階段。

  D、-XX:+CMSScavengeBeforeRemark,控制remark階段前進(jìn)行一次minor gc,來提高remark的效率,減少時(shí)間。

  CMS-remark(STW):重新標(biāo)記,處理上幾次以來可能引用關(guān)系發(fā)生變化的部分,并重新進(jìn)行標(biāo)記,這個(gè)階段會停止應(yīng)用線程

  CMS-concurrent-sweep:真正的清理階段,將以上幾個(gè)步驟標(biāo)記的無法訪問的對象進(jìn)行并發(fā)清理,并將清理的空間回收到空閑列表中

  CMS-concurrent-reset:調(diào)整堆大小,重置一些內(nèi)部的數(shù)據(jù)結(jié)構(gòu),為下一次回收做準(zhǔn)備

  3、缺點(diǎn)

  A、無法處理浮動垃圾,因?yàn)檫@是一款并發(fā)的收集器,程序運(yùn)行和收集的同時(shí)都會產(chǎn)生垃圾,所以回收時(shí)不能向其他收集器一樣等到滿了的時(shí)候再收集,通過-XX:CMSInitiatingOccupancyFraction=65設(shè)置觸發(fā)的百分比,留出一定的空間給并發(fā)收集的時(shí)候使用,當(dāng)CMS運(yùn)行期間無法滿足程序的需要,則會出現(xiàn),此時(shí)會臨時(shí)使用Serial Old作為臨時(shí)方案進(jìn)行一次標(biāo)記整理的回收,這樣就會使得出現(xiàn)較為長期的停頓,所以-XX:CMSInitiatingOccupancyFraction=65不能設(shè)置太高。

  B、由于是使用標(biāo)記清除算法的收集器,因此會產(chǎn)生內(nèi)存碎片,為了解決這個(gè)問題,垃圾收集器提供了一個(gè)-XX:+UseCMSCompactAtFullCollection的開關(guān)參數(shù),表示再一次FGC時(shí)進(jìn)行一次內(nèi)存整理的過程,這個(gè)過程是無法并發(fā)的,會拉長停頓時(shí)間,收集器還提供另一個(gè)參數(shù),-XX:CMSFullGCsBeforeCompaction=5表示FGC幾次后進(jìn)行一次內(nèi)存整理。

  4、優(yōu)化措施

  優(yōu)化目標(biāo):減少STW停頓時(shí)間

  優(yōu)化手段:

  A、降低觸發(fā)CMS回收的百分比,給并發(fā)收集時(shí)留出一定的空間,避免Concurrent Mode Failure,通過-XX:CMSInitiatingOccupancyFraction=65配置

  B、開啟內(nèi)存壓縮,避免碎片問題無法分配大內(nèi)存對象,通過-XX:+UseCMSCompactAtFullCollection和-XX:CMSFullGCsBeforeCompaction=5.具體數(shù)值可以按需調(diào)配。

  C、減少CMS-remark(STW)階段的時(shí)間,通過-XX:+CMSScavengeBeforeRemark、-XX:CMSMaxAbortablePrecleanTime=5000、-XX:CMSScheduleRemarkEdenPenetration=50進(jìn)行微調(diào)。

  5、相關(guān)參數(shù)

參數(shù)說明
-Xloggc:/dev/shm/xxx_gc.log設(shè)置GC日志路徑
-XX:+PrintGCDateStamps打印GC時(shí)間
-XX:+PrintGCDetails打印GC詳細(xì)信息
-XX:+PrintGCApplicationStoppedTime打印應(yīng)用停頓時(shí)間
-XX:+PrintGCApplicationConcurrentTime打印應(yīng)用當(dāng)前時(shí)間
-XX:+PrintSafepointStatistics打印安全點(diǎn)統(tǒng)計(jì)信息
-XX:+UnlockDiagnosticVMOptions解鎖診斷型參數(shù)
-XX:-DisplayVMOutput禁用控制臺輸出VM信息,例如安全點(diǎn)日志
-XX:+LogVMOutput啟用日志輸出VM日志
-XX:LogFile=/dev/shm/safepoint.log設(shè)置VM日志輸出路徑
-XX:CMSScheduleRemarkEdenPenetration=20設(shè)置Eden區(qū)使用率超過20%就進(jìn)入remark階段
-XX:CMSMaxAbortablePrecleanTime=1500設(shè)置可中斷預(yù)清理階段最大執(zhí)行時(shí)間
-XX:+CMSScavengeBeforeRemark設(shè)置期望進(jìn)入remark階段前進(jìn)行一次MinorGC
-XX:+PrintReferenceGC打印引用處理信息
-XX:+UseConcMarkSweepGC使用CMS收集器
-XX:+UseParNewGC使用ParNew收集器
-XX:+CMSParallelRemarkEnabledremark階段采用并行多線程模式
-XX:+UseCMSCompactAtFullCollection開啟壓縮整理功能
-XX:CMSFullGCsBeforeCompaction=0設(shè)置CMS多少次后進(jìn)行一次壓縮
-XX:+CMSClassUnloadingEnabled開啟回收永久代
-XX:+UseCMSInitiatingOccupancyOnly設(shè)置CMS回收時(shí)機(jī)一直按照Fraction配置進(jìn)行
-XX:CMSInitiatingOccupancyFraction=60設(shè)置老年代內(nèi)存使用率超過60時(shí)開始CMS回收
-XX:+AlwaysPreTouch啟動時(shí)申請所需內(nèi)存,避免系統(tǒng)調(diào)用延遲

  6、日志分析

  以下是一次完整的CMS回收日志,需要配置以下參數(shù) 

2019-07-17T21:54:50.216+0800: 190007.616: [GC [1 CMS-initial-mark: 1258440K(2097152K)] 1294890K(3984640K), 0.0365050 secs] [Times: user=0.04 sys=0.01, real=0.04 secs]2019-07-17T21:54:50.253+0800: 190007.654: Total time for which application threads were stopped: 0.0455330 seconds2019-07-17T21:54:50.254+0800: 190007.654: [CMS-concurrent-mark-start]2019-07-17T21:54:50.413+0800: 190007.813: [CMS-concurrent-mark: 0.159/0.159 secs] [Times: user=0.91 sys=0.02, real=0.16 secs]2019-07-17T21:54:50.413+0800: 190007.814: [CMS-concurrent-preclean-start]2019-07-17T21:54:50.413+0800: 190007.814: [Preclean SoftReferences, 0.0005560 secs]2019-07-17T21:54:50.414+0800: 190007.814: [Preclean WeakReferences, 0.0011690 secs]2019-07-17T21:54:50.415+0800: 190007.815: [Preclean FinalReferences, 0.0000350 secs]2019-07-17T21:54:50.415+0800: 190007.815: [Preclean PhantomReferences, 0.0000070 secs]2019-07-17T21:54:50.425+0800: 190007.825: [CMS-concurrent-preclean: 0.011/0.011 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]2019-07-17T21:54:50.425+0800: 190007.826: [CMS-concurrent-abortable-preclean-start]
CMS: abort preclean due to time 2019-07-17T21:54:51.938+0800: 190009.338: [CMS-concurrent-abortable-preclean: 1.508/1.512 secs] [Times: user=2.46 sys=0.16, real=1.51 secs]2019-07-17T21:54:51.938+0800: 190009.338: Application time: 1.6846120 seconds2019-07-17T21:54:51.946+0800: 190009.346: [GC[YG occupancy: 351451 K (1887488 K)]2019-07-17T21:54:51.946+0800: 190009.347: [GC2019-07-17T21:54:51.949+0800: 190009.350: [ParNew2019-07-17T21:54:51.979+0800: 190009.379: [SoftReference, 2284 refs, 0.0002550 secs]2019-07-17T21:54:51.979+0800: 190009.379: [WeakReference, 5 refs, 0.0000150 secs]2019-07-17T21:54:51.979+0800: 190009.379: [FinalReference, 679 refs, 0.0002280 secs]2019-07-17T21:54:51.979+0800: 190009.380: [PhantomReference, 0 refs, 0.0000120 secs]2019-07-17T21:54:51.979+0800: 190009.380: [JNI Weak Reference, 0.0000100 secs]: 351451K->23085K(1887488K), 0.0330260 secs] 1609892K->1282310K(3984640K), 0.0370030 secs] [Times: user=0.26 sys=0.01, real=0.04 secs]2019-07-17T21:54:51.984+0800: 190009.384: [Rescan (parallel) , 0.0272010 secs]2019-07-17T21:54:52.011+0800: 190009.411: [weak refs processing2019-07-17T21:54:52.011+0800: 190009.411: [SoftReference, 5341 refs, 0.0020150 secs]2019-07-17T21:54:52.013+0800: 190009.413: [WeakReference, 0 refs, 0.0000220 secs]2019-07-17T21:54:52.013+0800: 190009.413: [FinalReference, 80 refs, 0.0002020 secs]2019-07-17T21:54:52.013+0800: 190009.414: [PhantomReference, 0 refs, 0.0000120 secs]2019-07-17T21:54:52.013+0800: 190009.414: [JNI Weak Reference, 0.0000230 secs], 0.0023470 secs]2019-07-17T21:54:52.013+0800: 190009.414: [class unloading, 0.0198310 secs]2019-07-17T21:54:52.033+0800: 190009.434: [scrub symbol table, 0.0100610 secs]2019-07-17T21:54:52.043+0800: 190009.444: [scrub string table, 0.0011130 secs] [1 CMS-remark: 1259224K(2097152K)] 1282310K(3984640K), 0.1204410 secs] [Times: user=0.48 sys=0.02, real=0.12 secs]2019-07-17T21:54:52.067+0800: 190009.468: Total time for which application threads were stopped: 0.1293860 seconds2019-07-17T21:54:52.068+0800: 190009.468: [CMS-concurrent-sweep-start]2019-07-17T21:54:52.747+0800: 190010.147: [CMS-concurrent-sweep: 0.679/0.679 secs] [Times: user=1.24 sys=0.09, real=0.68 secs]2019-07-17T21:54:52.747+0800: 190010.147: [CMS-concurrent-reset-start]2019-07-17T21:54:52.753+0800: 190010.153: [CMS-concurrent-reset: 0.006/0.006 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]12345678910111213141516復(fù)制代碼類型:[java]

  通用字段解析

日志內(nèi)容含義
2019-07-17T21:54:50.216+0800GC發(fā)生的時(shí)間,系統(tǒng)當(dāng)前時(shí)間
190007.616虛擬機(jī)從啟動到現(xiàn)在經(jīng)過的時(shí)間
[Times: user=0.04 sys=0.01, real=0.04 secs]當(dāng)前過程耗時(shí)情況,user表示運(yùn)行用戶代碼時(shí)間,sys表示系統(tǒng)調(diào)用以及系統(tǒng)級等待的時(shí)間,real表示實(shí)際時(shí)間

  CMS-initial-mark

日志內(nèi)容含義
1258440K(2097152K)1258440K:回收前老年代占用大小,2097152K:老年代總大小
1294890K(3984640K)1294890K:整堆內(nèi)存占用大小,3984640K:堆內(nèi)存總大小

  CMS-concurrent-mark

日志內(nèi)容含義
[Preclean SoftReferences, 0.0005560 secs]該階段處理軟引用的時(shí)間
[Preclean WeakReferences, 0.0011690 secs]該階段處理弱引用的時(shí)間
[Preclean FinalReferences, 0.0000350 secs]該階段處理最終引用的時(shí)間
[Preclean PhantomReferences, 0.0000070 secs]該階段處理虛引用的時(shí)間
[CMS-concurrent-preclean: 0.011/0.011 secs]預(yù)清理階段耗費(fèi)的時(shí)間

  CMS-concurrent-abortable-preclean

日志內(nèi)容含義
[CMS-concurrent-abortable-preclean: 1.508/1.512 secs]可中斷預(yù)清理階段耗費(fèi)的時(shí)間,該階段并行,不會STW

  YG occupancy

日志內(nèi)容含義
GC[YG occupancy: 351451 K (1887488 K)表示該階段是MinorGC,351451表示年輕代占用大小,1887488年輕代總大小
351451K->23085K(1887488K), 0.0330260 secs351451K年輕代回收前大小,23085K年輕代回收后大小,1887488K年輕代總大小,耗時(shí)0.0330260

  CMS-remark

日志內(nèi)容含義
[Rescan (parallel) , 0.0272010 secs]重新標(biāo)記花費(fèi)的時(shí)間
[class unloading, 0.0198310 secs]類卸載花費(fèi)的時(shí)間
[scrub symbol table, 0.0100610 secs]刷新符號表耗費(fèi)的時(shí)間
[scrub string table, 0.0011130 secs]刷新常量池耗費(fèi)的時(shí)間?
[1 CMS-remark: 1259224K(2097152K)] 1282310K(3984640K), 0.1204410 secs]1259224K老年代占用大小,2097152K老年代總大小,1282310K堆內(nèi)存占用大小,3984640K堆內(nèi)存總大小,耗時(shí)0.1204410s

  四、實(shí)戰(zhàn)

  1、測試代碼

/**
 * 堆溢出測試
 * -Xms100m -Xmx100m -XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/dump.hprof
 *
 * @author Horace
 */public class HeapOOMTest {private static Logger logger = LoggerFactory.getLogger(HeapOOMTest.class);public static void main(String[] args) {int _1M = 1024 * 1024;
  List<byte[]> bytes = new ArrayList<>();while (true) {
   bytes.add(new byte[_1M]);
   LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1000));
  }
 }
}1234567891011121314151617復(fù)制代碼類型:[java]

  2、查看GC情況

  本地環(huán)境界面查看工具 jvisualvm

  每1秒輸出一次GC情況

  jstat -gccause pid 1s

  以下是GC情況

S0  S1  E   O   M  CCS YGC  YGCT FGC FGCT  GCT LGCC  GCC 89.83   0.00  42.05  37.10  94.37  90.41   2 0.025  0 0.000 0.025 Allocation Failure   No GC 89.83   0.00  46.58  37.10  94.37  90.41   2 0.025  0 0.000 0.025 Allocation Failure   No GC 89.83   0.00  51.00  37.10  94.37  90.41   2 0.025  0 0.000 0.025 Allocation Failure   No GC 89.83   0.00  54.74  37.10  94.37  90.41   2 0.025  0 0.000 0.025 Allocation Failure   No GC 89.83   0.00  58.49  37.10  94.37  90.41   2 0.025  0 0.000 0.025 Allocation Failure   No GC 89.83   0.00  63.69  37.10  94.37  90.41   2 0.025  0 0.000 0.025 Allocation Failure   No GC 89.83   0.00  67.44  37.10  94.37  90.41   2 0.025  0 0.000 0.025 Allocation Failure   No GC 89.83   0.00  71.19  37.10  94.37  90.41   2 0.025  0 0.000 0.025 Allocation Failure   No GC 89.83   0.00  75.71  37.10  94.37  90.41   2 0.025  0 0.000 0.025 Allocation Failure   No GC 89.83   0.00  79.46  37.10  94.37  90.41   2 0.025  0 0.000 0.025 Allocation Failure   No GC 89.83   0.00  83.98  37.10  94.37  90.41   2 0.025  0 0.000 0.025 Allocation Failure   No GC 89.83   0.00  87.72  37.10  94.37  90.41   2 0.025  0 0.000 0.025 Allocation Failure   No GC 89.83   0.00  92.14  37.10  94.37  90.41   2 0.025  0 0.000 0.025 Allocation Failure   No GC1234567891011121314復(fù)制代碼類型:[java]

  各個(gè)字段表示的含義可以查看:

  https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html#BEHHGFAE

  命令行dump內(nèi)存快照

  jmap -heap dump:live,format=b,file=/tmp/dump.hprof

  dump出來的內(nèi)存可以通過jprofile、mat、jhat等工具進(jìn)行分析

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多