JVM:G1垃圾回收器

 
 
 

===G1垃圾回收器是如何划分堆空间的呢?
G1垃圾回收器将内存分成一个个小块区域,这些小块区域的大小可以是1M,2M,4M,8M等等,并且这些小块区域可以是eden,survivor,old,以及humongous区域。其中humongous用来存大对象,如果一个对象超过某块空间的1/2的时候就会被认为是大对象来进行处理。
 

 

 
 
===G1如何进行对象空间分配的呢?
对于一个线程来说它有自己的eden区域,如果不够用就会使用公共的eden区域,再不够就使用老年代
 
 
===G1垃圾回收器有哪些GC的算法呢?
G1提供了三种GC模式,Young GC,old GC和Mixed GC,两种都是Stop The World(STW)的。
 
1.youngGC,eden区域空间耗尽了就进行的垃圾回收。
eden优先到survivor,不够就到老年代,survivor也会转移到新的survivor或者到老年代中去。目的是直到eden区域清空为止。
 
===young GC中如何标记被老年代引用的新生代呢?如何避免扫描所有的老年代?
因为有些老年代引用到新生代的对象,为了避免扫描整个老年代,所以使用卡表记录。
---CMS中在老年代有个RS(Remember set记录集合)数据区域记录指向新生代的引用:所以老年代中有个RS区域记录了老年代对新生代的引用,这样直接扫描这个RS区域就可以了不需要扫描整个老年代。
---G1中在每个分区使用卡表数组来进行记录Card Table。卡表记录这个分区的每个位置的使用情况,如果被引用了就标记成0,同时也在RS中进行记录。
我的理解就是老年代有个RS哈希表,键是某块新生代起始地址,value就是卡表,卡表里面记录哪块区域被引用,这样直接就扫这个RS和卡表就能够知道老年代引用了新生代什么对象了。
 
2.MIX GC混合式GC
当老年代的空间降低到一定程度了就触发Mix Gc。
过程很像CMS垃圾回收。主要分为两个步骤:全局并发标记和拷贝存活对象
---initial mark: 初始标记过程,整个过程STW,标记了从GC Root可达的对象
---concurrent marking: 并发标记过程,整个过程gc collector线程与应用线程可以并行执行,标记出GC Root可达对象衍生出去的存活对象,并收集各个Region的存活对象信息
---remark: 最终标记过程,整个过程STW,标记出那些在并发标记过程中遗漏的,或者内部引用发生变化的对象
---clean up: 垃圾清除过程,如果发现一个Region中没有存活对象,则把该Region加入到空闲列表中
 
---并发扫描过程中的三色标记算法
有黑色(根对象或者扫描过的对象),灰色(正在扫描对象),和白色(未扫描对象)三种。

 

 
---并发过程中可能出现的对象丢失问题如何解决呢?如何去标记被修改了的对象呢?

 

 

在并发修改的时候可能导致一个对象丢失的情况。比如以上C对象就被丢失掉了。如何解决呢?
CMS的解决方式:如果一个白对象被黑对象引用,直接就变成灰色。
G1中使用的方式是:开始标记的时候生成快照(STAB,snapshot-at-the-beginning),并发标记的时候某个对象被修改了就直接插入写屏障write barrier。
 
3.老年代GC
如果对象内存分配速度过快,mixed gc来不及回收,导致老年代被填满,就会触发 一次full gc,G1的full gc算法就是单线程执行的serial old gc,会导致异常长时间的暂停时间,需要进行不断的调优,尽可能的避免full gc.
===调优参数设置
最大暂停时间MaxGCPauseMillis
如果MaxGCPauseMillis设置的过小,那么GC就会频繁,吞吐量就会下降。如果MaxGCPauseMillis设置的过大,应用程序暂停时间就会变长。G1的默认暂停时间是200毫秒,我们可以从这里入手,调整合适的时间。
 
 
posted @ 2018-08-03 15:09  buptyuhanwen  阅读(1692)  评论(0编辑  收藏  举报