JVM:垃圾回收

判断对象是否存活

引用计数

假如对象被引用,则计数加1,计数为0时回收。但是存在循环引用问题:A引用B,B引用A,导致AB永远不能被回收。

可达性分析(JAVA采用的算法)

从GC Root出发看某个对象是否可达。假如不可达,则回收。

  • GC Root:存活时间很长的对象,有存在意义的对象。
    • 虚拟机栈中的局部变量表
    • static成员
    • 常量引用
    • 本地方法栈中的变量
    • 类加载器
    • Thread

回收算法

标记-清除

流程:先标记对象,然后将未存活的对象清除。
缺点:1、大量的空间碎片,内存不连续;2、标记和清除都比较耗时。

标记-复制

流程:先标记存活对象,复制到保留区域,再将当前区域的所有对象清除。
缺点:浪费了一半空间
优点:空间连续

标记-整理

流程:先标记存活对象,将存活对象移动到一边,清理边界外的所有对象。

垃圾收集器

分代使用垃圾收集器

新生代:标记-复制算法

新生代大部分对象都是朝生夕死,只有少量对象存活,复制成本低,适合复制算法

  • Serial:单线程,复制算法。单线程收集效率高;会停业务线程。
  • ParNew:多线程,复制算法。多线程收集;会停业务线程。
  • Parallel Scavenge:多线程,复制算法。更关注吞吐量。
老年代:标记-清除/标记-整理

老年代大量对象会存活,复制成本高,不适合使用复制算法

  • Serial Old:单线程,标记-整理算法。会停业务线程。
  • Parallel Old:多线程,标记-整理算法。更关注吞吐量。会停业务线程。
  • CMS:Concurrent Mark Sweep(用户线程和垃圾回收线程可以同时进行),更关注停顿时间(降低了对吞吐量的要求)。标记-清除算法
G1收集器

G1作用于新生代和老年代,根据期望的停顿时间进行选择性回收。而且G1对堆重新进行了布局,逻辑上还存在Eden,Survivor,Old,但是物理上已经不隔离了。

JVM调优

  • GC日志:停顿时间和吞吐量
    • 吞吐量:运行用户代码时间/(运行用户代码时间+垃圾收集时间):用户代码执行占CPU资源时间比较大,跑任务,运算的任务(Parallel Scanvenge + Parallel Old)并发类收集器,jdk1.8默认
    • 停顿时间:垃圾收集器进行垃圾回收Client执行响应的时间--->用户很好的体验--->和用户交互较多的场景(CMS,G1)并行类收集器,jdk1.9默认
  • 内存使用的维度
原文地址:https://www.cnblogs.com/fcb-it/p/13352683.html