JVM——GC

1、垃圾回收算法

1.1 垃圾标记

  • 引用计数——最简单的垃圾标记方式就是,对每一个对象指定一个引用计数器,每新增一个引用其对应的引用计数器加一,然后在垃圾回收时只需要判断当前对象的引用计数是否为0,即可进行清除。但是这会造成循环引用的问题,如果两个对象之间形成了循环引用,那将永远无法被标记。

  • 可达性分析——这种方式就是从“GC Roots”出发,寻找所有被其引用的对象(可达对象),对于不可达的对象则说明其没有存在引用,因此可以清楚。

    GC Roots 指的是位于方法区的静态变量、常量,位于虚拟机栈(栈帧中的局部变量表)中对象的引用,以及本地方法(native)中的对象的引用。

1.2 垃圾回收

  • 标记-清理算法:这种方式是最直接的,经过前一阶段的标记后直接进行垃圾回收,但是这会造成大量的内存碎片,所以基本上未使用。
  • 复制算法:鉴于上述方式产生的内存碎片,于是提出了复制算法,它需要jvm将内存提前划分为几部分,保留其中一部分不使用,然后将被标记的存活对象按序复制到该保留内存中,然后直接清除掉其他内存区域的对象。
    这种算法虽然实现简单,内存效率高,不易产生碎片,但是最大的问题是可用内存被压缩到了原本的一半。且存活对象增多的话,Copying 算法的效率会大大降低。
  • 标记-整理算法:鉴于上述内存利用率低,不适合大批量存活对象复制的问题,于是提出了标记-整理算法。该算法需要不断调整对象的内存地址,使存活对象保持连续地址,然后直接清除掉存活对象地址以外的所有内存数据即可。相对于复制算法而言,实现较为复杂,对于存在大批量的垃圾对象的时候,十分耗时,标记-整理算法效率会极具下降。
  • 分代回收:分代回收就是综合了上述两种方法而实现的。首先JVM将其运行时内存分为三部分:新生代、老年代、永久代。
    1. 新生代中的对象一般而言生命周期短,容易经常被回收,所以采取复制算法,当内存不足时,会产生Minor GC。

      新生代又可细分为:Eden、From Survivor、To Survivor三个区(8:1:1),也就是说新生代中可用内存空间为整个新生代容量的90%,有10%的内存被浪费。
      Eden:新对象的出生地。
      From Survivor:上一次GC的幸存者,作为这一次GC的被扫描者。
      To Survivor:保留MinorGC过程中的幸存者。
      【MinorGC的触发条件】:当Eden区内存不足的时候,虚拟机将进行一次MinorGC。Survivor区内存不足不会触发MinorGC。MinorGC之后,可能会与一些新生代的对象年龄满足进入老年代,老年代的占用会有所升高。

    2. 老年代中的对象一般而言生命周期较长,不容易被回收,所以采取标记-整理算法,当内存不足时,发生Full GC。

    3. 对于永久代而言,其基本上不会被回收,因为永久代又被称为方法区,其存放的是元信息,比如class、字面量等。只有当方法区达到内存临界点时,才会发起full gc。比如在大量使用反射、动态代CGLib等ByteCode框架、动态生成JSP以及OSGI这类频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的功能,以保证永久代不会溢出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值