《深入拆解 Java 虚拟机》学习总结

本文是对《深入拆解 Java 虚拟机》的学习总结,很不错的课程,推荐学习。

01 | Java代码是怎么运行的?

  • 虚拟机角度看
    以标准 JDK 中的 HotSpot 虚拟机为例,Java 代码首先被编译成class文件加载到 Java 虚拟机中。加载后的 Java 类会被存放于方法区(Method Area)中。实际运行时,虚拟机会执行方法区内的代码。
    在这里插入图片描述
    JVM内存模型解释

  • 硬件角度看
    Java 字节码无法直接执行,Java 虚拟机需要将字节码翻译成机器码。翻译过程有两种形式:
    1、解释执行:逐条将字节码翻译成机器码并执行;
    2、即时编译(Just-In-Time compilation,JIT):将一个方法中包含的所有字节码编译成机器码后再执行。
    在这里插入图片描述

02 | Java的基本类型

在这里插入图片描述

03 | Java虚拟机是如何加载Java类的?

类加载步骤:加载、链接(验证、准备、解析)、初始化三个步骤。

  • 加载
    查找字节流,并且据此创建类的过程,
    双亲委派模型。每当一个类加载器接收到加载请求时,它会先将请求转发给父类加载器。在父类加载器没有找到所请求的类的情况下,该类加载器才会尝试去加载。

  • 链接
    将创建成的类合并至 Java 虚拟机中,使之能够执行的过程。它可分为验证、准备以及解析三个阶段。
    验证阶段的目的,在于确保被加载类能够满足 Java 虚拟机的约束条件。
    准备阶段的目的,则是为被加载类的静态字段分配内存。
    解析阶段的目的,正是将这些符号引用解析成为实际引用。如果符号引用指向一个未被加载的类,或者未被加载类的字段或方法,那么解析将触发这个类的加载(但未必触发这个类的链接以及初始化。)

  • 初始化
    便是为标记为常量值的字段赋值,以及执行 < clinit > 方法的过程。Java 虚拟机会通过加锁来确保类的 < clinit > 方法仅被执行一次。

04 | JVM是如何执行方法调用的?(上)

  • 重载与重写
    1、重载
    定义:同一个类中,方法名相同,但参数个数或类型不同。
    调用:重载的方法在编译过程中即可完成识别。Java 编译器会根据所传入参数的声明类型(注意与实际类型区分)来选取重载方法。
    2、重写
    定义:子类与父类中有相同的方法名、请求参数、返回类型。
    调用:会根据调用者的动态类型,来选取实际的目标方法。

  • JVM 的静态绑定和动态绑定

11 | 垃圾回收(上)

  • 引用计数法
    为每个对象添加一个引用计数器,用来统计指向该对象的引用个数。一旦某个对象的引用计数器为 0,则说明该对象已经死亡,便可以被回收了。
    缺点:无法处理循环引用对象。

  • 与可达性分析
    将一系列 GC Roots 作为初始的存活对象合集(live set),然后从该合集出发,探索所有能够被该集合引用到的对象,并将其加入到该集合中,这个过程我们也称之为标记(mark)。最终,未被探索到的对象便是死亡的,是可以回收的。
    缺点:在多线程环境下,其他线程可能会更新已经访问过的对象中的引用,从而造成误报(将引用设置为 null)或者漏报(将引用设置为未被访问过的对象)。

  • Stop-the-world 以及安全点
    Stop-the-world:停止其他非垃圾回收线程的工作,直到完成垃圾回收。
    Java 虚拟机中的 Stop-the-world 是通过安全点(safepoint)机制来实现的。当 Java 虚拟机收到 Stop-the-world 请求,它便会等待所有的线程都到达安全点,才允许请求 Stop-the-world 的线程进行独占的工作。

  • 垃圾回收的三种方式
    1、清除(sweep),即把死亡对象所占据的内存标记为空闲内存,并记录在一个空闲列表(free list)之中。当需要新建对象时,内存管理模块便会从该空闲列表中寻找空闲内存,并划分给新建的对象。
    缺点:会造成内存碎片;分配效率较低。
    在这里插入图片描述
    2、压缩(compact),即把存活的对象聚集到内存区域的起始位置,从而留下一段连续的内存空间。这种做法能够解决内存碎片化的问题,但代价是压缩算法的性能开销。
    在这里插入图片描述
    3、复制(copy),即把内存区域分为两等分,分别用两个指针 from 和 to 来维护,并且只是用 from 指针指向的内存区域来分配内存。当发生垃圾回收时,便把存活的对象复制到 to 指针指向的内存区域中,并且交换 from 指针和 to 指针的内容。复制这种回收方式同样能够解决内存碎片化的问题,但是它的缺点也极其明显,即堆空间的使用效率极其低下。
    在这里插入图片描述

12 | 垃圾回收(下)

  • Java 虚拟机的堆划分
    Java 虚拟机将堆划分为新生代和老年代。其中,新生代又被划分为 Eden 区,以及两个大小相同的 Survivor 区。
    在这里插入图片描述
    Minor GC:Eden 区满了,Eden 区和 from 指向的 Survivor 区中的存活对象会被复制到 to 指向的 Survivor 区中,然后交换 from 和 to 指针。该过程采用了标记 - 复制算法。
    如果一个对象被复制的次数为 15(对应虚拟机参数 -XX:+MaxTenuringThreshold),那么该对象将被晋升(promote)至老年代。另外,如果单个 Survivor 区已经被占用了 50%(对应虚拟机参数 -XX:TargetSurvivorRatio),那么较高复制次数的对象也会被晋升至老年代。采用标记 - 复制算法。

垃圾回收器介绍

13 | Java内存模型

  • happens-before 关系
    是用来描述两个操作的内存可见性,具备传递性。

  • Java 内存模型的底层实现
    Java 内存模型是通过内存屏障(memory barrier)来禁止重排序的。

https://zhanghan.blog.csdn.net/article/details/109255980

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值