JVM-垃圾收集算法

2 篇文章 0 订阅

怎么判断一个对象是垃圾

判断算法

  1. 引用计数法

当别的对象引用该对象时,该对象内部计数器会加1,失效时计数器会减1,当计数器为0时,对象就会被回收

在这里插入图片描述

当栈中的obj引用堆中的obj1时,obj1内部计数器会加1,
obj1引用obj2时,obj2内部计数器也会加1,而同时obj2引用obj1,obj1内部计数器将会再加1。

在这里插入图片描述

引用计数器的问题:

  • 哪怕是栈里面的obj对堆里面obj1进行了释放,那么obj1的计数器还是不为零,如果两个对象相互依赖,导致内部的计数器用于不会0,导致永远不能被回收
  1. 可达性分析
    概念:可达性分析有一个 GC ROOT作为对象起始点,从这个节点开始向下搜索,搜索走过的路径成为引用链路,当一个对象没有任何GC ROOT引用链路时,则证明是不可达的,可以判断为该对象可以被回收
    在这里插入图片描述

由于顺着GC ROOT搜索可以找到person和car,所以这两个对象是可达的,不能回收,computer虽然跟mouse有关联,但是没有GC ROOT指向,所以是不可达的,是可以回收的对象

哪些可以成为GC ROOT呢

1、虚拟机栈的本地变量表:局部变量里面肯定是有线程在执行,所以不能回收
	例如:obj(GC ROOT) = 引用
2、静态(static)成员
3、常量
4、本地方法栈(C++)跟虚拟机栈类似
5、类加载 classloader:会一直在JVM虚拟机中

垃圾收集算法

  1. 标记清除算法
    两步:标记、清除
    • 标记:根据可达性分析,找出内存中需要回收的对象,把这些对象标记出来
      在这里插入图片描述
    • 清除:清除掉被标记需要回收的对象,释放出对应的内存空间
      在这里插入图片描述

缺点

标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序
运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次
垃圾收集动作。 
(1)标记和清除两个过程都比较耗时,效率不高 
(2)会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中
需要分配较大对象时,无 法找到足够的连续内存而不得不提前触发另一次垃圾
收集动作。
  1. 复制回收算法
    概念:将可用的内存按容量划分为大小相同的两块,每次只是用其中的一块。当发生垃圾回收时,将还存活着的对象复制到另一块上面,然后把已经使用过的内存空间一次清理掉,类似于堆中的S区
    在这里插入图片描述
    如果发生了GC,会把存活的对象复制到另一块区域,回收其他对象
    并且将存活的对象进行排序,形成连续的地址空间,从而不产生空间碎片
    在这里插入图片描述
    在这里插入图片描述
 优点:
   	  -高效
   	  -不会产生空间碎片
   缺点:
   	  -内存只能使用原来的一半
  1. 标记整理算法
    概念:该算法主要是为了解决标记-清除,产生大量内存碎片的问题;当对象存活率较高时,也解决了复制算法的效率问题。
    两步:标记、整理
    • 标记:标记过程仍然与"标记-清除"算法一样
      在这里插入图片描述
    • 整理:移动所有存活的对象,且按照内存地址依次排列,然后将存活对象的末端内存地址以后的内存全部回收
      在这里插入图片描述
      在这里插入图片描述
优点:不会产生空间碎片
  1. 分代收集算法
既然上面介绍了3中垃圾收集算法,那么在堆内存中到底用哪一个呢?

Young区:复制算法(对象在被分配之后,可能生命周期比较短,Young区复制效率比较高) 
Old区:标记清除或标记整理(Old区对象存活时间比较长,复制来复制去资源开销大,所以选择标记清除或标记整理)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值