第一天
什么是JVM
JVM本质上是一个运行在计算机上的程序,他的职责是运行Java字节码文件。
功能
1)解释和运行
对字节码文件中的指令,实时解读成机器码让计算机运行。
2)内存管理
自动为对象、方法等分配内存
自动的垃圾回收机制,回收不再使用的对象
3)即时编译
对热点代码进行优化,提高执行效率
常见JVM虚拟机
HotSpot
GraalVM
OpenJ9
DragonWell龙井
其中HotSpot被最广泛使用。
JVM的组成
第二天
打开字节码文件--jclasslib
字节码文件的组成
魔数Magic
文件是无法通过文件扩展名来确定文件类型的,文件扩展名可以随意修改,不影响文件的内容。
主副版本号
主副版本号指的是编译字节码文件的JDK版本号,主版本号用来标识大版本号,JDK1.0-1.1使用了45.0-45.3,JDK1.2是46之后每升级一个大版本就加1;副版本号是当主版本号相同时作为区分不同版本的标识,一般只需要关心主版本号。
版本号的作用主要是判断当前字节码的版本和运行时的JDK是否兼容
第三天
类的生命周期
类的生命周期描述了一个类加载、使用、卸载的整个过程。
生命周期的概述
加载阶段
1.加载阶段第一步是类加载器根据类的全限定名通过不同的渠道以二进制流的方式获取字节码信息。 程序员可以使用Java代码拓展不同的渠道。
2.类加载器在加载完类之后,Java虚拟机会将字节码的信息保存在方法区中。 3.类加载器在加载完类之后,Java虚拟机会将字节码中的信息保存到内存的方法区中。生成-个InstanceKlass对象,保存类的所有信息,里边还包含实现特定功能比如多态的信息。
对于开发者来说,只需要访问堆中的Class对象而不需要访问方法区中所有信息。 这样Java虚拟机就能很好地控制开发者访问数据的范围。
第四天
连接阶段
类的生命周期 连接阶段之验证
连接(Linking)阶段的第一个环节是验证,验的主要目的是检测Java字节码文件是否遵守了《Java虚拟机规范》中的约束。这个阶段一般不需要程序员参与。
主要包含如下四部分,具体详见《Java虚拟机规范》:
1.文件格式验证,比如文件是否以0xCAFEBABE开头,主次版本号是否满足当前Java虚拟机版本要求。
2.元信息验证,例如类必须有父类(super不能为空)。
3.验证程序执行指令的语义,比如方法内的指令执行中跳转到不正确的位置。
4.符号引用验证,例如是否访问了其他类中private的方法等。\
类的生命周期 验证案例-版本号的检测
主版本号不能高于运行环境主版本号,如果主版本号相等,副版本号也不能超过。
类的生命周期 连接阶段之准备
准备阶段为静态变量(static)分配内存并设置初始值。
注意:本章涉及到的内存结构只讨论JDK8及之后的版本,8之前的版本后续章节详述\
类的生命周期 连接阶段之解析
解析阶段主要是将常量池中的符号引用替换为直接引用。
直接引用不在使用编号,而是使用内存中地址进行访问具体的数据
初始化阶段
类的生命周期 初始化阶段
初始化阶段会执行静态代码块中的代码,并为静态变量赋值。
初始化阶段会执行字节码文件中clinit部分的字节码指令。
以下几种方式会导致类的初始化:
1.访问一个类的静态变量或者静态方法,注意变量是final修饰的并且等号右边是常量不会触发初始化
2.调用Class.forName(String className)。
3.new一个该类的对象时。
4.执行Main方法的当前类
clinit指令在特定情况下不会出现,比如:如下几种情况是不会进行初始化指令执行的,
1.无静态代码块且无静态变量赋值语句。
2.有静态变量的声明,但是没有赋值语句。
3.静态变量的定义使用final关键字,这类变量会在准备阶段直接进行初始化。\
第五天
类加载器
什么是类加载器
类加载器(ClassLoader)是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术。
类加载器只参与加载过程中的字节码获取并加载到内存这一部分。
类加载器的分类
类加载器分为两类,一类是Java代码中实现的,一类是Java虚拟机底层源码实现的。
Arthas中类加载器相关的功能
类加载器的详细信息可以通过classloader命令查看:classloader-査看 classloader 的继承树,urls,类加载信息,使用 classloader 去 qetResource