Java虚拟机-初识GC

作者: 李冬冬 | 来源:发表于2016-10-12 10:08 被阅读79次

    对象的结构

    一般来说,对象由头(head)和域(field)两个部分组成,如下图所示

    对象结构
    其中head主要包含了对象的大小,种类以及一些gc需要信息。field主要用于存储对象中可访问的部分,也就是我们平时看到的对象的方法变量之类的

    对象的生与死

    目前主要的对象判活算法有 可达性分析算法引用计数算法

    • 可达性分析算法通过从 GC Roots 开始向下搜索,如果一个对象没有在引用链上存在时,则判定对象可以被回收
    • 引用计数算法通过给对象添加一个引用计数器,通过引用计数判断对象是否存活,由于引用计数算法无法解决循环引用的问题,主流的Java虚拟机都没有采用这种方法。但是由于其实现方便,效率高的特点,可以作为一种辅助手段存在

    对象的生活环境

    就像人类的社会有资本主义和社会主义的划分,对象的生活环境也不相同。目前常见的垃圾回收算法有 标记清除算法(mark-sweep)标记压缩算法(mark-compact)复制算法(copying)

    • mark-sweep分为 marksweep 两个阶段:首先标记出所有需要回收的对象,然后统一回收这部分对象。
    • mark-compact在标记阶段与mark-sweep相同,但是后续会将对象向堆的一端移动,并清除边界外的所有对象。
    • copying将可用内存分成两个部分,一块内存使用完了之后将活着的对象移动到另一块内存,再把使用过的内存一次清理掉。

    时间开销

    • mark-sweep: mark阶段与活对象的数量成正比,sweep阶段与整堆大小成正比(不需要移动对象,开销比compact小)
    • mark-compact: mark阶段与活对象的数量成正比,compact阶段与活对象的大小成正比
    • copying: 与活对象成正比

    空间开销

    • mark-sweep: 小(产生碎片)
    • mark-compact: 小(不产生碎片)
    • copying: 通常需要活对象的2倍大小(不产生碎片)

    分配对象开销

    mark-sweep由于有内存碎片的存在,分配对象需要通过查询当前内存使用情况,选择一块适合的内存分配,因此mark-sweep在分配内存的时候存在额外的时间开销。而mark-compact和copying分配对象不需要考虑这种情况

    对象的辈分

    一般情况下将Java堆分为 新生代老年代
    对象的分配优先放在新生代,新生代在一段时间内会有大量的临时对象产生,因此存活的对象比较少,比较适合copying算法。对象在经过一定次数的copying gc之后会升级到老年代。老年代一般采用mark-sweep和mark-compact算法,正常情况下运行的是mark-sweep,在内存碎片达到一定程度的时候启动mark-compact。大对象直接存放到老年代。

    参考:

    1. 并发垃圾收集器(CMS)为什么没有采用标记-整理算法来实现?
    2. 深入理解Java虚拟机

    相关文章

      网友评论

        本文标题:Java虚拟机-初识GC

        本文链接:https://www.haomeiwen.com/subject/zfciyttx.html