Java内存垃圾回收


这里记录一下Java内存中的垃圾回收的相关内容。垃圾回收就是找到垃圾,在合适的时间用合理的方法将不用的内存回收。

如何识别垃圾

垃圾回收讨论的是堆内存里面的对象。

什么是垃圾

以后永远不再被使用的对象就是垃圾。

识别算法

引用计数法

每个对象搞一个引用计数器,有别的地方引用,计数器加1;原来引用现在不再引用,计数器减1。当计数器为0时,没有任何地方引用到这个对象,这个对象就无法再被访问,就识别为垃圾。

优势

算法简单。

问题

循环引用或者引用孤岛。形成孤岛以后,对象没有办法被访问,但是引用计数不是0,无法被回收。

扩展知识

引用类型

引用类型对象是否可引用回收时间使用场景
强引用 Strongly Reference可以不回收一般对象
软引用 Soft Reference可以内存不足时内存敏感的高速缓存
弱引用 Weak Reference可以下一次GC对象缓存
虚引用 Phantom Reference不可以下一次GC,不影响对象生命周期必须和引用队列(ReferenceQueue)一起使用,一般用于追踪垃圾收集器的回收动作。相比对象的finalize方法,虚引用的方式更加灵活和安全。

根可达性分析

GC Roots对象到该对象之间有引用,是可达的,就认为该对象不是垃圾,如果不可达,该对象是不可用的(不一定是垃圾)。

不可用的对象不一定被判定为可以回收的对象:判定对象为”死亡”至少需要经历两次标记的过程。

  1. 第一次标记:对象可达性分析,如果发现对象没有与GC Roots相连接的引用链,且对象需要执行finalize方法,将会被加入F-Queue队列中。
  2. 第二次标记:由一个优先级低的Finalizer线程去取F-Queue队列的对象,“尝试执行”对象的finalize方法。

JVM会保证触发满足条件的对象的finalize方法,但是并不承诺会等待方法执行结束。finalize方法是对象逃脱死亡命运的最后一次机会。

哪些对象可以作为GC Roots
  1. 虚拟机栈里面引用的对象
  2. 本地方法栈引用的对象
  3. 方法区中静态属性引用的对象
  4. 方法区中常量引用的对象

何时回收垃圾

主动回收

主动调用System.gc(),不推荐。

系统自动调用

系统觉得内存不够的时候。下面讨论一些虚拟机常用的收集方法,过程中可以看到什么情况下算内存不够。

如何回收垃圾

分代收集理论

  1. 弱分代假说:绝大多数对象朝生夕死
  2. 强分代假说:熬过越多次回收的对象越难以消亡
  3. 跨代引用假说:跨代引用占极少数

标记-清除算法

找到需求清除的内存对象,标记,然后统一清除。是一个基础算法

缺陷

  1. 执行效率不稳定
  2. 内存碎片

标记-复制算法

每次只使用一半空间,另外一半留着,如果标记完成,就把不需要清除的统一复制到另外一半内存,然后把原来一半清空作为待复制区。循环即可。

缺陷

  1. 内存利用率低
    采用优化算法可以提高利用率,但是总是有些内存是不能被使用的。
    新生代使用这种算法。
    分代示意图
    默认Eden取与survivor to区比值是8:1,两个survivor区一样大。
    新对象构造出来先进Eden区,Eden区快满了,就把Eden区和from区的标记,然后拷贝到to区。如果太多,由老年代担保,放入老年代。拷贝完成之后,to和from的名字对调。如果直接来了一个特别大的对象,直接进入老年代。Eden去加上from区还有to区都是新生代,新生代GC叫young GC 或者 minor GC。对象在新生代GC超过15次还没有被回收就会放到老年代。

标记-整理算法

标记好了,移动存活的对象指针,空出剩余区域。
老年代使用这种算法,效率低,stop the world。
折中办法:平时标记清除,碎片太多分配不了了,就统一整理一把。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值