java+g1+xmn_JVM Java G1 垃圾收集器

本文简单介绍了垃圾收集的几种常见式,重点说明了G1回收的原理(毕竟JDK1.9 G1会是默认的GC回收器–--我们讨论的只针对采用HotSpot VM 的openJDK、Oracle

JDK)

如您已对几种常见的GC 回收原理有所了解,请您直接跳到最后一章 G1使用。

一、垃圾回收是什么

三种GC 回收方法

在我们了解G1之前,我们先回顾一下JVAV GC的技术特点。

自动内存管理,有效的避免了因为“忘记释放”,导致内存无法重复使用从而产生内存泄漏。

现在采用的方法

1.标记-扫描

2.标记-复制

3.标记-整理

JVM中有一个非常具体和明确的对象集,称为垃圾收集根(Garbage Collection Roots)

注:所谓根(Root),就是判断对象是否可被引用的起始点,至于哪里才是根,不同的语言和编译器都有不同的规定,但基本是将变量和运行栈空间作为根

包含以下内容

1局部变量

2 活动线程

3静态字段

4JNI引用

JVM用于跟踪所有可到达(实时)对象并确保不可访问对象声明的内存可以重用的方法称为标记和扫描算法。它包括两个步骤:

标记正在遍历所有可到达的对象,从GC根开始并在本机内存中保留有关所有此类对象的分类帐

扫描确保下一次分配可以重用未引用对象占用的内存地址。

JVM中的不同GC算法(例如Parallel Scavenge,Parallel Mark + Copy或CMS)正在以略微不同的方式实现这些阶段,但在概念层面,该过程仍然类似于上述两个步骤

关于这种方法的一个至关重要的事情是循环不再泄漏:

cc0e9801fbce

图1来源网络

但此种标记清理回收带来的问题是,需要暂停应用线程以便收集,因为如果程序一直在变化,便无法计算真正的引用,当应用程序暂停以便JVM进行内部引用整理,这种情况就是我们所说的停止世界“stop the wordpause”

注:标记和扫描算法在概念上使用最简单的垃圾处理方法,只需忽略这些对象。这意味着在标记阶段完成后,未访问对象占用的所有空间都被视为自由空间,因此可以重用以分配新对象。

这种方法需要使用所谓的自由列表记录每个自由区域及其大小。自由列表的管理增加了对象分配的开销。这种方法的另一个弱点是,可能存在大量的空闲区域,但是如果没有一个区域足够大以适应分配,那么分配仍然会失败(在Java中有OutOfMeMyRebug错误)。

cc0e9801fbce

当进行清理时,JVM必须确保可以重用填充了无法访问的对象的区域(图1中灰色部分)。这可能(并最终会)导致内存碎片,与磁盘碎片类似,会导致两个问题:

写操作变得更加耗时,因为找到足够大小的下一个空闲块不再是一个简单的操作。

在创建新对象时,JVM会在连续的块中分配内存。因此,如果碎片升级到没有单个空闲片段足以容纳新创建的对象的点,则会发生分配错误。

为避免此类问题,JVM确保碎片不会失控。因此,垃圾收集过程中也会发生“内存碎片整理”过程,而不仅仅是标记和扫描。此过程将所有可到达对象重新定位到彼此旁边,从而消除(或减少)碎片。这是一个例子:

cc0e9801fbce

注:Mark-Sweep-Compact  算法通过将所有标记对象移动到存储区域的开头来解决Mark和Sweep的缺点。这种方法的缺点是增加了GC暂停持续时间,因为我们需要将所有对象复制到新位置并更新对这些对象的所有引用。Mark和Sweep的好处也是可见的 -在这样的压缩操作之后,通过指针碰撞,新的对象分配再次非常便宜。使用这种方法,自由空间的位置始终是已知的,并且也不会触发碎片问题。

cc0e9801fbce

Jave heap

堆中的内存池的基本上是以下划分的。在不同的GC算法中,某些实现细节可能会有所不同,但概念仍然有效。

cc0e9801fbce

Eden

Eden是内存中通常在创建对象时分配对象的区域。由于通常有多个线程同时创建大量对象,因此Eden进一步划分为 驻留在Eden空间中的一个或多个Thread Local Allocation Buffer(简称TLAB)。这些缓冲区允许JVM直接在相应的TLAB中分配一个线程内的大多数对象,从而避免与其他线程的昂贵同步。

当无法在TLAB内部进行分配时(通常因为那里没有足够的空间),分配将移至共享的Eden空间。如果那里没有足够的空间,则会触发Young Generation中的垃圾收集过程以释放更多空间。如果垃圾收集也没有在Eden中产生足够的可用内存,那么该对象将在旧代中分配。

收集Eden时,GC会从根部遍历所有可到达的对象,并将它们标记为活着。

我们之前已经注意到,对象可以具有跨代链接,因此直接的方法必须检查从其他代到Eden的所有引用。不幸的是,这样做将首先击败几代人。JVM有一个技巧:卡片标记。从本质上讲,JVM只是标记了伊甸园中“脏”物体的粗略位置,这些物体可能与老一代有关。

cc0e9801fbce

标记阶段完成后,Eden中的所有活动对象都将复制到其中一个Survivor空间。整个伊甸园现在被认为是空的,可以重复使用来分配更多的物体。这种方法称为“标记和复制”:活动对象被标记,然后被复制(不移动)到幸存者空间。

注:标记和复制算法与标记和压缩非常相似,因为它们也会重新定位所有活动对象。重要的区别是,搬迁的目标是一个不同的记忆区域,作为幸存者的新空间。标记和复制方法有一些优点,因为在同一阶段复制可以与标记同时发生。缺点是还需要一个足够大的内存区域来容纳幸存的对象。

cc0e9801fbce

Survivor

在Eden空间旁边有两个叫做from和to的Survivorspaces(幸存者空间)。重要的是要注意两个幸存者空间中的一个总是空的。

空闲的幸存者空间将在下一次年轻一代被收集时开始让对象进驻。来自整个Young一代的所有存在引用连接对象(包括Eden空间和来自'Survivor空间的非空')被复制到'to'幸存者空间。完成此过程后,'to'现在包含对象,'f

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值