JVM内存模型,GC垃圾回收算法,对象创建过程

JVM虚拟机的具体详解

    • 内存模型
    • GC垃圾回收算法
    • 判断一个对象是否回收
    • CMS垃圾回收(标记-清除)
    • G1垃圾回收(标记-整理)-初始标记、并发标记、最终标记、筛选回收
    • JVM对象创建过程

内存模型

JVM内存模型,GC垃圾回收算法,对象创建过程_第1张图片

  1. 方法区Method Area(HotSpot VM也称为永久代):线程共享,主要是存放类定义、常量、静态变量和类编译后的代码等。JDK1.7中HotSpot VM也称为永久代(可以直接使用堆中的GC进行管理,永久代经常出现内存溢出),在1.8中取消了永久代,改变为元空间(基于电脑内存实现,不怕内存溢出)
  2. 堆 Heap:几乎所有的数组、对象等都在这里分配内存,是GC算法的主阵地,有新生代(Minor GC)和老年代(Major GC)
  3. 虚拟机栈 VM Stack:线程私有,执行方法时,在此区域中创建一个栈帧来存放方法的各种返回值、局部变量表和各种对象引用,开始执行创建栈帧入栈,执行完成后出栈
  4. 本地方法栈 native method stack:和虚拟机栈一样,只不过专门为Native方法使用的
  5. 程序计数器 program counter register:记录当前执行的行数、分支、跳转、循环、异常处理、线程恢复等基础功能

GC垃圾回收算法

*复制、标记-清除、标记-整理、分代收集

  1. 复制:从Roots开始扫描,将可以关联的对象都进行标记,将标记的节点复制到一块空闲的内存中,然后统一将原区域的内存回收(新生代)
  2. 标记-消除:先从Roots节点开始扫描一遍并进行标记,在第二遍扫描时将标记未标记的对象进行内存回收
  3. 标记-整理:将标记好的对象都向同一端移动,然后回收端边界以外的内存
  4. 分带回收:将堆分为新生代和老年代,不同的代适应不同的算法

判断一个对象是否回收

判断一个对象是否被回收需要进行两次标记。
第一次从roots对象作为起点进行搜索,搜索路径为“引用链”,当一个对象到roots没有“引用链”时被判断为不可用对象。
第二次继续从roots对象进行搜索,当不可用对象还是没有“引用链”时,被判断为可回收对象,进行内存回收。
注:不可用对象到可回收对象需要两次标记,能否回收还要看finalize()方法有没有与引用对象关联。

CMS垃圾回收(标记-清除)

初始标记和重新标记需要“stop the world”
优点:并发标记、低停顿
缺点:无法处理浮动垃圾,可能会产生“Concurret model failuer”失败导致Full GC的产生,对CPU资源敏感,占用一部分线程使程序变慢,总吞吐量降低

  • 初始标记:仅仅标记一下roots的关联对象
  • 并发标记:进行GC Roots tracing过程
  • 重新标记:在进行并发标记的时候,用户程序一直在运行,重新标记一下运行时产生的对象
  • 并发清除:回收未标记对象

G1垃圾回收(标记-整理)-初始标记、并发标记、最终标记、筛选回收

  • 并发与并行:1能充分利用CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短stop-The-World停顿时间,部分Java程序需要停下执行来去GC动作,但G1可以利用多线程的优势继续让java程序执行
  • 分代设计:它能够采用不同的方式去处理新创建的对象和已经存活了一段时间,熬过多次GC的旧对象以获取更好的收集效果。
  • 空间整合:与CMS的“标记–清理”算法不同,G1从整体来看是基于“标记整理”算法实现的收集器;从局部上来看是基于“复制”算法实现的。
  • 可预测停顿:但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,

JVM对象创建过程

常量池中定位类的符号引用

检查符号引用所代表的类是否已被加载,解析和初始化过 →
↓ ↓
分配内存(类加载完成后,内存需求确定) ← 加载

根据java堆是否规整(GC方法)选择分配方法
↙ ↘
指针碰撞 空闲列表

分配内存的并发保证(指针更新的原子性)
↙ ↘
CAS+失败重试 按照线程划分在不同的空间中进行TLAB -XX:+UseTLAB -XX:-UseTLAB

内存空间初始化为0值,保证对象的实例字段可以不赋初值就可以使用。

设置对象头信息(Object Header):引用指针,元数据,hash值,GC分代年龄,锁相关

执行对象方法

你可能感兴趣的:(Java基础解析)