垃圾收集器与内存分配策略

一、判断对象是否死亡

1.引用计数算法:
给对象中添加一个引用计数器。当对象实例每被引用一次计数器+1,每一个引用失效计数器-1;当计数器为0时,对象可被回收;

缺点:对象相互引用时,计数器的值永不为0;
2.可达性分析算法
通过一系列的"GC Roots"对象作为起点,从这些节点开始向下搜索,所走过的路程称为引用链,当一个对象没有与任何引用链相连,则证明对象不可用;

Java中可以作为GC Roots的对象

  1. 虚拟机栈中的引用对象
  2. 本地方法栈中的Native方法引用的对象
  3. 方法区中类静态属性的引用对象
  4. 方法区中常量的引用对象

3.回收方法区

  • 回收方法区的废弃常量:当没有对象引用方法区中的常量时,常量被判定为废弃常量
  • 回收无用的类:类的所有实例被收回,加载该类的ClassLoader被收回,该类对应的对象没有在任何地方被引用;

二、垃圾收集算法

1.标记 - 清除算法
标记过程如同以上判定对象死亡时的标记相同;
清除过程就是对标记对象进行删除的过程;

缺点:效率低。并且清除后产生大量不连续内存碎片。

2.复制算法
复制算法就是把内存分为两块,只使用其中的一块,当进行回收时把存活的对象复制到另一块内存中,然后在使用的那块内存进行垃圾回收。这样提高了效率,解决了内存碎片问题。
复制算法适用于新生代:在HotSpot虚拟机中新生代的内存分为8:1:1。使用8和1进行信息的存放,把存活的对象复制到剩下的1内存中。
空间不够时,依赖其他内存进行分配担保。

3.标记 - 整理算法
标记过程和上文相同。
整理过程是让存活对象都向一端移动,之后把端边界以外的内存直接清理。
标记 - 整理算法适用于老年代:对象存活率较高时,复制算法的效率就会变低。
老年代的存活率高,所以采用标记 - 整理算法的效果更好。

4.分代收集算法
分代收集算法就是对于不同对象的存活周期将内存划分成不同的块。例如JAVA堆中划分的新生代和老年代。根据特性采用不同的垃圾收集算法。

三、HotSpot虚拟机算法实现

  1. 枚举根节点:
    问题:使用可达性分析算法进行垃圾收集,GC Roots遍历引用,耗时长。
    在进行可达性分析要确保一致性,而此时的线程都在变化。
    解决:使用准确式GC。在HotSpot中通过OopMap的数据结构来实现准确式GC。使用OopMap记录偏移量。
  2. 安全点:Java堆中发生变化的引用太多,如果记录每个OopMap空间成本太高。所以把让程序执行时间长的部分定义为安全区,记录下来。
    实现:当GC需要中断线程时,设置一个标志,当线程执行到标志时,判断为真,当前线程挂起。
  3. 安全区域:当程序不执行,JVM中毒单请求,线程无法挂起。在安全区域中的引用关系不会发生变化,虚拟机可以在安全区域中完完整的执行GC。

四、垃圾收集器

  1. CMS收集器:
    CMS收集器用于回收老年代的对象。采用标记 - 清除算法。所以使用CMS收集器之后产生的内存空间是不规整的。
    CMS收集器主要经过四个步骤实现:
    初次标记、并发标记、重新标记、并发清除
    缺点:空间不规整。低于四核降低执行速度。无法处理浮动垃圾。

  2. G1收集器:
    G1收集器可以用于回收新生代和老年代。把内存划分成一块块Region区域。回收时从整体上看采用标记 - 整理算法。局部 Region采用复制算法。
    G1收集器主要经过四个步骤实现:
    初次标记、并发标记、最终标记、筛选回收。

  3. Serial/Serial Old收集器:
    单线程的收集器。在进行垃圾收集时暂停所有的线程,单线程的方式方式进行垃圾收集。新生代使用复制算法。老年代使用标记 - 整理算法。

  4. ParNew/ParNew Old收集器:
    使用多线性进行垃圾回收,其他的部分和Serial收集器类似。

  5. Parallel Scavenge收集器:
    "吞吐量优先"收集器。它和ParNew类似采用是新生代收集器,采用复制算法,并行多线程收集。其他的收集器注重于减短暂停线程的时间,但是Parallel Scavenge更注重达到一个可控制的吞吐量。
    通过设置停顿时间和吞吐量大小来实现自适应调节。

五、内存分配与回收策略

  1. 对象在新生代的Eden区域进行分配内存。当Eden和Survivor空间不足时发生Minor GC回收对象。
    把存活的对象利用复制算法分配进入另一个Survivor区域。如果Survivor不够存放存活对象,通过分配担保,对象进入老年代。
  2. 大对象对于虚拟机分配是坏消息,例如长字符串或者数组。可以通过设置参数使大对象直接进入老年代。
  3. 虚拟机给每个对象定义一个对象年龄计数器。从Eden出生开始进行一次Minor GC对象年龄计数器+1,当(默认)计数器达到15时进入老年代。
  4. 在Survivor区域中相同年龄的对象大小总和等于或超过Survivor容量的50%,那么对象直接进入老年代。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值