JVM笔记2:垃圾收集器

  • JVM的垃圾收集器(Garbage Collector)管理的是Java堆方法区的垃圾回收。
  • GC需要完成三件事:哪些内存需要回收(即判定垃圾)?什么时候回收?如何回收(垃圾收集算法)?

垃圾判定算法

引用计数算法

  • 对指向对象的引用进行计数,当计数器值归零时则删除该对象。
  • 但是当出现循环引用时,相关的对象永远无法被判定为垃圾。

可达性分析算法

       该算法基本思路如下:

  • 选定一系列对象作为根对象“GC Roots”,根据引用关系向下搜索,搜索走过的路径称为“引用链”
  • 如果某个对象到“GC Roots”之间没有任何引用链相连,则证明此对象是不可能再被使用的

       固定选为“GC Roots”的对象有以下几类:

  • 在虚拟机栈中引用的对象。(局部变量、临时变量等)
  • 在方法区中类静态变量和常量引用的对象
  • 在本地方法栈中JNI(即本地方法)引用的对象
  • JVM内部的引用
  • 所有被同步锁持有的对象

       除此以外,不同的垃圾收集器还有自己的选择。

引用的类型:无论哪一种垃圾判定算法都与引用有关,在JDK1.2版本之后扩充了引用的概念:

  • 强引用:即平时最常见的引用关系,有强引用的对象一定不会被回收
  • 软引用:在首次回收后如果还没有足够的内存,才会回收只有软引用的对象(SoftReference类)
  • 弱引用:比软引用更弱,在垃圾收集器开始工作时,无论内存是否足够,只有弱引用的对象都会被回收(WeakReference类)
  • 虚引用:最弱的引用关系,甚至无法从虚引用获取对象实例,更无法对对象的生存时间构成影响。(PhantomReference类)

垃圾收集算法

分代收集理论

       当前商业虚拟机的垃圾收集器大部分都基于“分代收集(Generational Collection)”的理论。分代收集理论基于以下假说:

  1. 弱分代假说(Weak Generational Hypothesis):绝大多数对象都是朝生夕灭的。
  2. 强分代假说(Strong Generational Hypothesis):熬过越多次垃圾收集过程的对象就越难以消亡。
  3. 跨代引用假说(Intergenerational Reference Hypothesis):跨代引用相对于同代引用来说仅占极少数。

       基于以上假说的垃圾收集器会将其管理的内存划分为不同的区域,并根据各区域的特点以不同的频率各自执行不同的垃圾收集算法。具体来说,至少会有“新生代(Young Generation)”和“老年代(Old Generation)”两类区域。在新生代中,每次垃圾收集时都会有大批对象被回收,存活的少量对象会逐渐被移动到老年代中。据此可以总结以下特点:

  • 新生代中的大部分对象都很容易被回收,因此需要以较高的频率执行垃圾收集算法;同时每次垃圾收集后的新生代区域中的对象会很稀疏。
  • 老年代中的大部分对象难以消亡,因此垃圾回收的频率比较低;并且每次垃圾收集后会产生较小的碎片。

       因此在不同的区域中需要执行不同的垃圾收集算法。常见的垃圾收集算法有以下几种。

标记-清除算法

  • 标记-清除(Mark-Sweep)算法是最早最基础的垃圾收集算法(算法示意图如下)
  • 过程:第一阶段根据垃圾判定算法标记出需要回收(或需要存活)的对象;第二阶段清除(或保留)被标记的对象。
  • 缺点:一是执行效率不稳定,容易随着对象数量增长而降低;二是内存会产生较多的碎片,导致触发过多不必要的GC动作。

sweep

标记-复制算法

半区复制,Semispace Copying
  • 过程:将内存分为大小相等的两半,每次只使用其中一半。当执行垃圾收集时,就把仍存活的对象依次复制到另一半,再把已使用过的一半直接清理掉。
  • 缺点:一是如果内存中多数对象是存活的,就会产生大量的复制开销;二是可用内存缩小了一半。
    copying
Appel式回收

根据IBM一项研究,新生代中的对象98%都熬不过第一轮收集,因此并不需要按照半区复制中1:1的比例来划分新生代的内存空间。

  • 为了优化半区复制的空间代价,可以将新生代分为一块较大的Eden空间和两块较小的Survivor空间。每次分配内存只使用Eden和其中一块Survivor,垃圾收集时将所有的存活对象复制到另一块Survivor中,然后清理掉已使用的两块空间。
  • HotSpot虚拟机默认的Eden和Survivor大小比例为8:1,即只有10%的空间是被浪费的。
  • 如果垃圾收集后有大于10%的对象存活,需要依赖其他内存区域(实际上大多就是老年代)保存多出来的存活对象。

标记-整理算法

  • 由于标记-复制算法需要其他内存区域的担保,因此老年代不能直接用这种算法。标记-整理(Mark-Compact)算法就是针对老年代提出的。
  • 过程:标记阶段后,让所有存活的对象向内存空间的一端移动。
  • 缺点:与简单的标记-清除算法比,移动操作有较重的负担,会延长GC的延迟。(相应的,由于没有碎片,内存分配会更加简单)。
  • Compromise:在老年代上,平时多数时间都采用标记-清除算法;直到内存空间的碎片化程度已经大到影响对象分配时,在采用标记-整理算法收集一次以清理碎片。
    compact
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值