Java 垃圾收集

怎样判断对象是否被回收

1.引用计数算法:每个对象有一个引用计数器, 当引用计数器为0(没有被引用)时就回收对象(无法解决循环引用问题)

2.可达性分析算法:从根开始向下搜索,搜索走过的路径称为引用链, 当一个对象到根没有任何引用链的时候就说明不可达, 不可达的对象就可以被回收

java虚拟机中使用的不是引用计数算法

垃圾收集算法

1.标记-清除算法: 先对要回收的对象做上标记, 全部标记完成后同一回收

缺点:效率较低,回收之后会产生大量空间碎片, 导致以后分配大对象时找不到足够空间

2.复制算法:将可用内存划分为大小相等的两块, 当其中一块的内存用完时,将其中存活的对象复制到另一块的前面(后面是一整块空闲区间用来存放新的对象), 运行高效, 但内存缩小为原来的一半. 后来将内存分为一块较大的Eden空间和两块较小的Survivor空间, 回收时将Eden和Survivor中存活的对象一次性复制到另外一块Survivor空间上, 然后清理掉原来的两块空间, 当Survivor空间不够时需要依赖老年代进行分配担保.

缺点: 会损失一定空间, 在存活对象较多时会进行较多的复制操作, 效率会变低

3.标记-整理算法: 先对要回收的对象做上标记, 然后让存活的对象往一端移动, 然后清理掉边界以外的内存.

4.分代收集算法: 根据对象存活周期不同将内存划分为几块,然后针对不同块使用最合适的收集算法.

对象回收过程

1.判断对象是否应该被回收

2.要回收对象, 如果对象没有覆盖finalize()方法或者finalize()方法已经被调用过, 就不用执行finalize()方法

3.如果要执行finalize()方法,那么这个对象将会放在一个队列中, 然后由虚拟机自动创建的一个低优先级的Finalizer线程去执行这个队列的finalize()方法(不会承诺等待这个方法运行结束)

3.如果在执行finalize()方法过程中又重新引用了这个对象, 那么这个对象不会被回收(只能有一次, 因为只会调用一次finalize()方法,下一次会直接回收)

一般不会使用finalize()方法.

垃圾收集器

安全点(safepoint):可以理解成是在代码执行过程中的一些特殊位置,当线程执行到这些位置的时候,说明虚拟机当前的状态是安全的, 可以进行垃圾回收(进行垃圾回收的时候引用关系不能变化), 安全点位置主要在循环末尾方法返回前, 可能抛异常的位置等.

安全区域:一段代码中引用关系都不会发生变化, 这个区域任何地方都可以进行垃圾回收.

在进行垃圾收集时, 垃圾收集器会让所有线程运行到最近的安全点上停下来, 主要采用主动式中断(抢先式中断不使用)方法,

不直接对线程操作, 只设置一个标志, 各个线程执行时主动去查看这个标志, 如果为真, 就自动在安全点挂起.

1.Serial收集器: 单线程, 收集垃圾时暂停所有线程, 直到收集结束, 新生代采取复制算法, 老年代采取表记-整理算法

2.ParNew收集器: 多线程, 收集方式和Serial相同, 只是在新生代使用了多个线程

3.Parallel Scavenge收集器: 可以通过参数来设置吞吐量(吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间))

4.CMS 收集器: 以获取最短回收停顿时间为目标的收集器, 主要分为四个步骤执行

    a.初始标记, 暂停所有线程, 标记GC Roots(一组必须活跃的引用), 时间很短

    b.并发标记, 和用户线程同时执行(并发), 从GC Roots开始标记出不可达对象

    c.重新标记, 暂停所有线程, 修正并发标记期间因用户线程运行而导致标记产生变动的那一部分,时间远比并发标记短

    d.并发清除, 和用户线程一起并发执行, 清理被标记的对象.

    缺点:会占用cpu资源导致应用程序变慢, 无法处理浮动垃圾(并发清理阶段产生的垃圾), 标记-清除算法会产生空间碎片

5.G1收集器: 并行与并发, 充分利用硬件优势缩短停顿时间, 分代收集, 并且将每一个分代又分为多个小区域, 在执行垃圾回收时优先回收垃圾最多的区域从而避免全堆扫描以提高效率 

内存分配与回收策略

1.大多数情况下,对象在新生代Eden区分配, 当Eden区没有足够空间时虚拟机将发起一次Minor GC(新生代的垃圾收集)

2.当进行垃圾回收后如果新生代空间仍然不够, 就将新生代的存活对象通过分配担保机制提前转移到老年代去

3.当创建对象特别大时(大于虚拟机的一个参数), 虚拟机就直接将这个对象分配到老年代

4. 长期存活的对象将进入老年代. 虚拟机给每一个对象定义了一个年龄计数器, 如果对象在Eden出生并经过第一次Minor GC后仍然存活并能被Survivor容纳的话, 将被移动到Survivor空间中(复制算法), 并将对象年龄设为1, 对象在Survivor区中每熬过一次Minor GC, 年龄就增加一岁, 当年龄增加到一定程度(默认为15岁), 就将这个对象移动到老年代中.

5.如果Survivor空间中相同年龄的所有对象大小总和大于Survivor空间的一半, 年龄大于等于该年龄的对象也可以直接进入老年代

空间分配担保

发生Minor GC之前, 虚拟机会先检查老年代最大可用连续空间是否大于新生代所有对象的总空间, 如果这个条件成立, 那么Minor GC确保是安全的(可以进行分配担保), 如果不成立, 虚拟机会查看HandlePromotionFailure设置是否允许担保失败, 如果允许, 那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小, 如果大于, 将尝试进行一次Minor GC(有风险), 如果小于, 或者HandlePromotionFailure设置不允许冒险, 那么这时也要改为进行一次Full GC(老年代的垃圾收集) 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值