zoukankan      html  css  js  c++  java
  • Java的GC是什么?做了什么?

    Java GC是Java的垃圾回收机制

    • Java堆是被所有线程共享的一块内存区域,所有对象实例和数组都在堆上进行内存分配。为了高效的进行垃圾回收,虚拟机把堆内存分为新生代,老年代和永久代3个区域
    • 新生代可以分为Eden区和Survivor Space(S0,S1)区,大多数情况下,对象在Eden区分配,当Eden没有足够的内存空间时触发一次Minor GC
    • Survivor是幸存区,是新生代和老年代的缓冲区域,当新生代发生MinorGC时,会将存活的对象从Eden区移动到S0内存区域,并清空Eden区,当再次发生Minor GC时,将Eden和S0中存活的对象移到S1区;存活对象反复在S0和S1移动,当对象在Surivivor之间移动或者从Eden移动到Surivivor区时,对象的GC年龄会不断增加,当GC年龄超过默认阈值15会进入老年代
    • 老年代用于存放经过几次MinorGC后依然存活的对象,当老年代空间不足时会触发Full GC/Major GC,速度比MinorGC慢十多倍

    如何判断对象是否存活

    • 引用计数法

    对象上添加一个引用计数器,每当有一个对象引用它时,计数器加1,当使用完该计数器时,计数器减1,计数器为0表示该对象不被使用

    优点:实现简单,判定高效

    缺点:无法解决对象之间相互引用的问题

    • 可达分析法

    通过一系列的GC Roots对象作为起点,从这些起点开始向下搜索,搜索路径称为引用链

    可作为GC Roots的对象:

    1. 本地变量表中引用的对象 / 虚拟机栈中引用的对象
    2. 方法区中静态变量引用的对象
    3. 方法区中常量引用的对象
    4. Native方法引用的对象

    当一个对象到GCRoots没有任何引用链时,就表示该对象可以被回收

    使用可达性分析法判断一个对象是否可被回收需要经过两次标记:

    1. 对象ObjectA到GC Roots没有引用链,进行第一次标记
    2. 如果ObjectA重写了finalize方法,且还未执行过,那么ObjectA会被插入到一个F-Queue队列中,再由一个虚拟机自动创建的,低优先级的Finalizer线程触发其finalize方法。finalize方法中如果对象ObjectA与引用链中的对象建立联系,那么在进行第二次标记时ObjectA会被移出即将回收的集合(注:finalize方法只会被JVM调用一次)

    GC算法:

    • 标记清除(老年代)

    对待回收的对象进行标记

    缺点:标记和清除过程效率都很低,收集之后会留下很多内存碎片,不利于大对象的分配

    • 复制(年轻代)

    将内存分为大小相等的A和B两份,每次只使用一份,A中内存用完了,就把A中存活的对象复制到B中,并清空A的内存

    优点:只需要标记存活的对象,标记效率得到提高;避免了内存碎片的问题

    缺点:可用内存缩小为原来的一半

    • 标记整理(老年代)

    老年代中,对象的存活率较高,复制算法效率比较低,在标记整理算法中,标记出所有存活的对象并移到一端,然后直接清理边界以外的内存

  • 相关阅读:
    MVP社区巡讲照片集
    周末之个人杂想(十六)
    SQL Server 2014 BI新特性(二)结合Data Explorer和GeoFlow进行数据分析
    SQL Server 2014 BI新特性(一)五个关键点带你了解Excel下的Data Explorer
    Tabular Model下的ADOMD.NET
    玩玩Excel下的Power View
    LeakCanary,30分钟从入门到精通
    Android热修复技术总结
    阿里最新热修复Sophix与QQ超级补丁和Tinker的实现与总结
    热修复——深入浅出原理与实现
  • 原文地址:https://www.cnblogs.com/qf123/p/8528147.html
Copyright © 2011-2022 走看看