JVM系列4——垃圾回收算法

一、确定对象死亡的方法

        确认对象的存活都和引用有关。目前确定对象已死有两种方式引用计数算法和可达性分析算法。

1.引用计数法:在对象中添加一个引用计数器,当对象被引用的时候+1,引用失效-1。为0的对象就不存在引用。这种方法实现简单,判断效率比较高。弊端就是两个对象相互引用,无其他地方调用,使用引用计数法无法回收。

2.可达性分析:GCroot的对象作为起始点,从这些节点向下搜索,搜索所有的路径为引用链。一个对象到GCroot没有任何链接的时候。就是不可达对象。 不可达对象不代表可以直接回收,处于缓刑阶段。不可达对象要经过两次标记的过程,两次标记后仍然是不可达对象,将会面临被回收。

GCroot对象的定义

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象,比如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。
  • 方法区类中静态属性引用的对象,比如java类的引用类型静态变量。
  • 方法区中常量引用的对象,比如字符串常量池。
  • 本地方法栈中引用的对象(native)。
  • 同步锁持有的对象
  • JVM内部的引用,比如基本数据类型对应的class对象,系统类加载器。
  • 反应java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。

3.java中的引用类型分为:软引用、弱引用、虚引用、强引用。

强引用:普通的变量引用,基本不会回收。强引用容易造成内存泄漏。

public static User user = new User();

软引用:SoftReference实现,内存不足才会被回收。gc之后空间不够存储新对象,软饮用会被回收。回收后内存还不足,内存溢出。

public static SoftReference<User> user = new SoftReference<User>(new User());

弱引用:WeakReference实现,垃圾回收就会被回收,不关心内存是否够用。

public static WeakReference<User> user = new WeakReference<User>(new User());

虚引用:phantomReference实现,不能单独使用,必须和引用队列联合使用,虚引用主要用于跟踪对象被垃圾回收的状态。

4.回收方法区(永久代回收):永久代基本能回收的很少,主要两部分无用常量和没有引用的类。无用常量是定义的常量代码在所有类中都没有引用可以回收。没有引用的类要回收需要满这个类和类下面的方法均没有引用,不存在该类任何类的实例。加载该类的classloader已经被回收。该类对应java.lang.class对象没有在任何地方引用,无法在任何地方使用反射访问该类的方法。

二、垃圾回收算法

        程序中每个对象都有对应的作用域,超过这个作用域就不可在用。如果想尽快回收不可用对象,可以把不用的对象设置为null(可能会有空指针)。减少对象的作用域,大方法拆分成n个小方法,把大方法中的变量变成小方法中的变量。

1、标记-清除算法

        标记出所有需要清除的对象(不可达对象),之后进行删除。缺点就是标记清除算法效率低,如果Java堆中包含大量对象并且大部分需要回收,必须进行大量的标记和删除,导致效率低。 容易产生内存碎片,标记、清除后会产生大量不连续的内存碎片,碎片过多如果进来大对象会提前触发又一次垃圾回收。

2、标记-复制算法

        将内存分为两块区域,每次使用一块,当这一块用完了,将还活着的对象放到另外一块区域。把已使用的一块清理掉。这样会减少内存碎片。实行简单,运行高效。缺点就是内存缩小为原来的一半。如果对象存活率比较高的时候就要进行较多的复制操作,效率将会降低。

 3、标记-整理算法

        首先把需要回收的对象标记出来,存活的对象移动到一个区域,之后直接清理掉边界之外的需要回收的对象。这样不用担心产生内存碎片。

 4、分代回收算法

        大部分JVM都会采用分代收集算法。根据对象存活周期的不同将内存分为几块。一般会将堆分为新生代和老年代。这样就可以根据年代的特点结合适合的垃圾回收算法。

新生代复制算法: 新生代大部分对象存活时间短,垃圾收集是大批量死亡,只有少量存活。将新生代分区做复制算法。新生代划分为 eden去 和两个 Survivor区,按照8:1:1区分。每次使用eden空间和一块Survivor区域,gc时两快区域存活的对象放到to区域。这一次gc的幸存者是下一次gc的参与者。

Eden(8)

Survivor From (1)

Survivor To(1)

老年代标记--整理算法:老年代对象存活时间比较久,GC少量对象被回收。

老年代对象来源

  1. 对象的内存分配主要在新生代的eden和Survivor区域,少数对象会直接分配到老年代,大对象或者大的数组。
  2. 新生代GC的时候,to 区域空间无法满足的时候回直接放到老年贷。
  3. Survivor区域存活一次就年龄+1,一般年龄到达15的时候会放到老年代。年龄在jvm参数的时候可配置。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值