【java】JVM垃圾收集与内存分配策略

JVM垃圾收集与内存分配策略

文章目录

  • JVM垃圾收集与内存分配策略
    • 内存分配与回收策略
    • 判断对象是否存活
    • 垃圾回收算法
    • 垃圾收集器


内存分配与回收策略

  • 对象优先在Eden区分配

  • 大对象直接进入老年代-XX:PretenureSizeThreshold 参数,大于这个设置值的对象直接在老年代分配,这样做的目的是避免在 Eden 区及两个 Survivor 区之间发生大量的内存复制。

    • 长期存活的对象将进入老年代JVM 给每个对象定义了一个对象年龄计数器。当新生代发生一次 Minor GC 后,存活下来的对象年龄 +1,当年龄超过一定值时,就将超过该值的所有对象转移到老年代中去。使用-XXMaxTenuringThreshold 设置新生代的最大年龄,只要超过该参数的新生代对象都会被转移到老年代中去。
  • 动态对象年龄判定:如果当前新生代的 Survivor 中,相同年龄所有对象大小的总和大于 Survivor 空间的一半,年龄 >= 该年龄的对象就可以直接进入老年代,无须等到 MaxTenuringThreshold 中要求的年龄。

  • 空间分配担保:通过清除老年代中废弃对象来扩大老年代空闲空间,以便给新生代作担保。

可能触发JVM进行 Full GC的情况:

  • System.gc() 方法的调用
  • 老年代空间不足

判断对象是否存活

  • 引用计数法:在对象头维护着一个 counter 计数器,对象被引用一次则计数器 +1;若引用失效则计数器 -1。当计数器为 0 时,就认为该对象无效了。弊端:难解决对象之间循环引用的问题。

  • 可达性分析法:所有和 GC Roots 根对象直接或间接关联的对象都是有效对象,和 GC Roots 没有关联的对象就是无效对象。

    GC Roots 包括:

    • Java 虚拟机栈(栈帧中的本地变量表)中引用的对象
    • 本地方法栈中引用的对象
    • 方法区中常量引用的对象
    • 方法区中类静态属性引用的对象

    GC Roots 并不包括堆中对象所引用的对象,这样就不会有循环引用的问题。

垃圾回收算法

分代收集理论

  • 复制算法(新生代)

  • 标记-清理

  • 标记-整理

垃圾收集器

过渡
过渡
serial
parallel
CMS
G1
serial+CMS组合
parNew + CMS组合
parallel scavenge + serial old组合
parallel scavenge + parallel old组合
G1
  • Serial 最早出现的垃圾收集器

单线程,在进行垃圾收集时,会暂停其他工作线程(stop the world)

  • ParNewserial的多线程并行版,新生代收集器(与serial一样带有空间压缩整理的能力,采用指针碰撞的分配算法来给对象分配内存);

  • Serial old

  • parallel Scavenge

致力于达到一个可控制的吞吐量(吞吐量=用户线程执行时间/用户线程执行时间+垃圾收集线程执行时间)

  • parallel old
  • CMS:老年代的收集器,(基于清除算法,采用空闲列表来给对象分配内存);

首次实现了让垃圾收集线程与用户线程(基本上)同时工作,致力于缩短回收停顿时间。

​ 运作过程

初始标记
Gc root能直接关联的对象
并发标记
遍历整个对象图
重新标记
修正并发标记期间由于用户线程继续运作导致标记产生变动的对象的标记记录
并发清除
清理删除掉并发标记阶段判断已经死亡的对象
  • G1

面向全堆的收集器,不需要和其他收集器配合一起工作

使用region划分内存空间,并且维护优先级列表(跟踪各个region区域回收所获得的空间大小以及回收所需时间数据)

​ 运作过程

初始标记
并发标记
最终标记
筛选回收

你可能感兴趣的:(java,jvm,java)