简述Java虚拟机的GC过程


一. 垃圾回收所针对的区域

首先Java虚拟机中共有五大内存区域:
程序计数器,Java虚拟机栈,本地方法栈,java堆,方法区

为什么不针对前三个区域: 对于前三种内存区域,他们的生存周期都是与线程相同,并且这些线程在运行之前就已经可以从类结构中确定他们所需内存,因此不需要过多的考虑他们的内存回收。

为什么针对后两个区域: 而对于java堆和方法区则不同,比如,一个泛型数组 new ArrayList(),指向的是一个父类接口,具体存储的子类由终端交互获得,然后才创建,这种情况在编译器就不可能知道具体需要分配多大的内存了。

因此垃圾回收机制主要针对的是: java堆和方法区

由于方法区的垃圾回收在java虚拟机规范中并没有强制要求,因此下面主要讨论的是在堆中的垃圾回收机制,而方法区将在稍后单独提及。
👇

二. 垃圾回收过程

先回答三个问题:

  1. 什么时候回收?
  2. 哪些需要回收?
  3. 如何回收?

什么时候? 当需要内存,但是内存又不够的时候,将会触发回收机制。

Created with Raphaël 2.2.0 需要内存 内存够吗? 分配内存 结束 启动垃圾回收 yes no

哪些需要回收? 有两种算法判断一个对象是否需要回收:

  1. 引用计数算法: 简单说就是给每个对象一个计数器,如果有引用就递增,引用失效就递减,当这个值任意时刻都为0,则此对象不可用。
    优点:简单,效率高。
    缺点:很难解决对象之间的相互循环引用。
  2. 根搜索算法: 使一些对象当做树的根(GC Roots),如何没有到根的引用路径,则此对象不可用。
    可作为根的对象有:
    a. Java虚拟机栈中引用的对象
    b. 方法区中的类静态属性引用的对象
    c. 方法区中常量引用的对象
    d. 本地方法栈中Native方法引用的对象

如何回收? 回收的方式有三种:

  1. 标记——清楚算法: 就是标记好需要回收的内存之后,直接清理,这样做的缺点在于:效率低,产生大量额空间碎片。
  2. 复制算法: 此算法和下面的算法一样,都是在标记——清楚算法的基础上,提高他的效率,减少空间碎片做努力。复制算法的思想将内存分为两类区域,一类用来实际使用,一类用来在回收时作为中转空间,既将在回收后还存活的对象放入这个中转空间,然后直接清楚掉另一类空间的所有内容。
    在这里插入图片描述
  3. 标记——整理算法: 这个算法是将标记之后依然存活的的对象依次重新从一端开始放入,然后清楚调用后面所有的内存。
  4. 分代收集算法: 这个算法将内存区域分为新生代老年代。故名思意,新生代代表这个区域类的对象流动快,更新快。而老年代则与此对立,流动慢,更新慢。而根据他们各自的特点,新生代主要使用的是复制算法,老年代主要使用的是标记——整理算法。
分代特点主要使用算法
新生代对象更新快复制算法
老年代对象更新慢标记——整理

接下来就是垃圾回收的具体过程👇

Created with Raphaël 2.2.0 利用引用计数器算 法或根搜索算法标记 出不可用对象 是否重写 finalize()方法 且第一次调用? 是否在finalize() 方法中自救 且逃离回收? 结束 根据对象所处分 代,利用各自算法 实现的收集器进 行垃圾回收 yes no yes no

其中对finalize()方法的判断是因为,利用引用计数器或根搜索算法标记出来的对象并不是一定会被清楚,而是还需要接下来的两次判断。也就是说,只有当覆盖了finalize()方法,并且是第一次调用,才有机会在这个方法中让这个被判死刑的对象起死回生!

方法区的回收: 方法区中存放了,类的信息,常量,静态变量,即时编译器生成的代码和数据,以及运行时常量池。 而方法区的回收,主要针对的就是常量池类的卸载

常量池回收与堆相似,如果常量池中的常量没有任何一个对象引用,那么就会被回收。

而对于类的卸载就麻烦许多,它需要满足下面三个条件才能回收:

  • 该类所有的实例都已经被回收,也就是Java堆中不存在任何实例。
  • 加载该类的ClassLoader已经被回收。
  • 该类对应的Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

三. 七种垃圾收集器对比

收集器算法应用代线程支持特点
Serial收集器复制算法新生代单线程简单高效,但GC过程中会停止所有用户线程
ParNew收集器复制算法新生代多线程与Serial差不多,能与CMS配合工作
Parallel Scavenge收集器复制算法新生代并行多线程注重吞吐量,具有自适应调节策略
Serial Old收集器标记——整理老年代单线程Serial老年代版本
Parallel Old 收集器标记——整理老年代并行多线程Parallel Scavenge老年代版本
CMS收集器标记——清除老年代并发收集并发手机,低停顿,但是对CPU资源敏感,无法处理浮动垃圾,由于使用标记——清除算法所以会产生大量空间碎片。
G1收集器标记——整理非分代方式高吞吐量,低停顿
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值