欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JVM垃圾回收二:算法实现------思维导图

程序员文章站 2022-05-21 23:29:00
...

前言

本博客为前一篇文章《JVM垃圾回收一:基本思想------思维导图》的垃圾回收算法具体设计与实现

垃圾回收算法

JVM垃圾回收二:算法实现------思维导图

思维导图大纲

一. 垃圾收集算法
1. 理论(假设)基础
  • 弱分代假说:绝大多数对象都是朝生夕灭的(活的很短)
  • 强分代假说:熬过越多次垃圾收集过程的对象,就越难以消亡
  • 跨代引用相对于同代引用来说,仅占极少数
2. 虚拟机实现

垃圾收集器应该将java堆划分出不同的区域,将对象按照其年龄分配到不同的区域来缓存"

  1. 新生代(Young Generation)

对朝生夕灭的对象,虚拟机将其分派在新生代区域中。垃圾回收系统只需要关注少量的存活对象,能以较低代价回收到大量的空间

  1. 老年代(Old Generation)

对于难以消亡的对象,虚拟机将其分派在老年代区域中。垃圾回收系统以较低的频率去回收此区域的对象,这样开销更低效果更好"

  1. 记忆集(Remembered Set)
  • 新生代上建立的一个全局的数据结构
  • 记忆集把老年代划分成若干块,标出哪一块内存存在跨代引用
  • 发生Minor GC时,只有在[跨代引用关系的小块内存]里的对象才会被加到GC Roots进行扫描,缩小了回收检索的范围
3. 垃圾收集
1. 部分收集(Partial GC)			
    - 新生代收集(Minor GC/Young GC)	
		 	目标只是新生代的垃圾收集	
	- 老年代收集(Major GC/Old GC)		
			目标只是老年代的垃圾收集	
			目前只有GMS收集器会有单独收集老年代的行为	
	- 混合收集(Mixed GC)		
			目标是收集整个新生代以及部分老年代的垃圾收集	
			目前只有G1收集器有这样的收集策略	
2. 整堆收集(Full GC)		
		对整个Java堆和方法区的垃圾收集		
4. 垃圾收集算法
1. 标记-清除(Mark-Sweep)			
		  - 首先标记需要回收对象;在标记完成后,统一回收掉标记的对象		
		  - 反过来也可以,先标记不需要回收的对象;然后清除掉没有标记的对象,完成回收		
		  - 最早也是最基础的收集算法		
	  - 缺点		
		  + 执行效率不稳定:如果堆中包含大量可回收对象,则效率降低	
		  + 内存空间存在碎片化:碎片化越来越多可能会引起一次Full GC,花费时间长	
2. 标记-复制(Mark-Copy)	
		  - 将内存按容量分为大小相等的两块,每次只用其中一块	
		  - 当这一块内存空间用完了,就把其中存活的对象复制到另一块	
		  - 复制完成后,将前一块空间全部清除掉做回收	
		  - 两块内存空间依次交替使用,来实现垃圾回收	
	  - 缺点:可用内存只有一半,空间浪费严重	(实际上,新生代中的对象有98%熬不过第一轮收集	)
		
	 - 优化的复制-标记策略  Eden+Servivor	
		  + 将新生代分为一块较大的Eden空间和两块较小的Survivor空间	
		  + 每个具体的时间点,虚拟机只使用一块Eden和一块Survivor来储存对象	
		  + 垃圾回收时,将其中存活的对象复制到之前没用到的另一块Survivor中	
		  + Hotspot虚拟机的Serial、ParNew等新生代收集器都采用此策略	
		  + 老年代因为存活率高,会有大量存活对象,不适合用复制算法		
3. 标记-整理(Mark-Compact)		
				标记整理算法与标记复制很像,不同点在于:不复制,是整理
		- 让所有的对象都向内存空间一端移动,然后直接清理掉边界以外的内存	
		- 存活对象过多的话,""移动""对象负重较大,此时必须全程暂停用户应用程序,会影响效果和体验
		- 不整理(移动)又会出现标记-清除的碎片化	
	+ 妥协的优化方案		
		- 让虚拟机平时多数时间采用标记-清除算法,暂时容忍碎片化存在	
		- 当碎片化多到影响对象内存分配是,再采用标记-整理算法收集一次	
		- 基于标记-清除算法的CMS收集器在碎片过多时,会采用此方法"
	+ 此算法多用在老年代