G1垃圾收集器

1.以前收集器特点

年轻代和老年代是各自独立且连续的内存块
年轻代收集使用单eden+S0+s进行复制算法

老年代收集必须扫描整个老年代区域
都是以尽可能少而快速地执行GC为设计原则。

2.概念

G1(Garbage-First)收集器,是一款面向服务端应用的收集器,应用在多处理器和大容量内存环境中,在实现高吞吐量的同时,尽可能的满足垃圾收集暂停时间的要求。另外还具有一下特性:

  • 像CMS收集器一样,能与应用程序线程并发执行。
  • 整理空间空间更快
  • 需要更多的时间来预测GC停顿时间
  • 不希望牺牲大量的吞吐性能
  • 不需要更大的Java Heap

G1收集器的设计目标是取代CMS收集器,它同CMS相比,在以下方面表现的更出色:

  • G1是一个有整理内存过程的垃圾收集器,不会产生很多内存碎片。
  • G1的Stop The World(STW)更可控,G1在停顿时间上添加了预测机制,用户可以指定期望停顿时间。

3.原理

区域化内存划片Region,整体编为一系列不连续的内存区域,避免了全内存的GC操作。

核心思想是将整个堆内存区域分成大小相同的子区域(Region),在JVM启动时会自动设置这些子区域的大小。

在堆的使用上,G1并不要求对象的存储一定是物理上连续的只要逻辑上连续即可,每个分区也不会固定地为某个代服务,可以按需在年轻代和老年代之间切换。启动时可以通过参数-XX:G1HeapRegionSize=n可指定分区大小(1MB-32MB,且必须是2的幂),默认将整个堆划分为2048个分区。
大小范围在1MB-32MB,最多能设置2048个区域。也即能够支持的最大内存为:32MB*2048=65536MB=64G内存。

G1将新生代、老年代的物理空间取消了。

G1算法将堆划分为若干个区域(Region),它仍然属于分代收集器

这些Region的一部分包含新生代,新生代的垃圾收集依然采用暂停所有应用线程的方式,将存活对象拷贝到老年代或者Survivor空间。

这些Region的一部分包含老年代,G1收集器通过将对象从一个区域复制到另一个区域,完成了清理工作。这就意味着,在正常的处理过程中,G1完成了堆的压缩(至少是部分堆的压缩),这样也就不会有CMS内存碎片问题的存在了。

在G1中,还有一种特殊的区域,叫Humongous(巨大的)区域。如果一个对象占用的空间超过了分区容量的50%以上,,G1收集器就认为这是一个巨型对象。这些巨型对象默认直接会被分配在老年代,但是如果它是一个短期存在的巨型对象,就会对垃圾收集器造成负面影响。为了解决这个问题,G1划分了一个Humongous区,它用来专门存放巨型对象。如果一个H区装不下一个巨型对象,那么G1会寻找连续的H分区来存储。为了能找到连续的H区,有时候不得不启动Full GC。

4.回收步骤

G1收集器下的Young GC

针对Eden区进行收集,Eden区耗尽后会被触发,主要是小区域收集+形成连续的内存块,避免内存碎片。
Eden区的数据移动到新的Survivor区,部分数据晋升到Old区。
Survivor区的数据移动到新的Survivor区,部分数据晋升到Old区。
最后Eden区收集干净了,GC结束,用户的应用程序继续执行。

  • 初始标记:只标记GC Roots能直接关联到的对象
  • 并发标记:进行GC Roots Tracing的过程
  • 最终标记:修正并发标记期间,因程序运行导致标记发生变化的那一部分对象
  • 筛选回收:根据时间来进行价值最大化的回收。

常用配置参数(了解)

-XX:+UseG1GC
-XX:G1HeapRegionSize=n:设置的G1区域的大小。值是2的幂,范围是1MB到32MB。目标是根据最小的Java堆大小划分出约2048个区域。
-XX:MaxGCPauseMillis=n:最大GC停顿时间,这是个软目标,JVM将尽可能(但不保证)停顿小于这个时间。
-XX:InitiatingHeapOccupancyPercent=n:堆占用了多少的时候就触发GC,默认为45
-XX:ConcGCThreads=n:并发GC使用的线程数。
-XX:G1ReservePercent=n:设置作为空闲的预留内存百分比,以降低目标空间溢出的风险,默认值是10%

5.和CMS相比的优势

两个优势:
G1不会产生内存碎片是可以精确控制停顿。
该收集器是把整个堆(新生代、老生代)划分成多个固定大小的区域,每次根据允许停顿时间去手机垃圾最多的区域。

G1垃圾收集器_第1张图片

你可能感兴趣的:(高并发)