JVM
文章目录 |
---|
基于《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》 |
目前主要针对OpenJDK及OracleJDK的HotSpot虚拟机进行学习
一、阶段梳理
针对学习路径的一个概括性梳理
1.1 番外资料
文章目录 |
---|
Java虚拟机(JVM)面试题(2020最新版)_ThinkWon的博客 |
/ |
JVM速成手册 | IT宅-arthinking’s blog |
1.2 编译流程
(1)Java源文件 👉(2)编译 👉 (3)生成class字节码文件 👉(4) JVM加载类
后续的笔记目录也将根据这套流程进行深入分析
二、JVM
2.1 知识点整理
- JVM运行时候的数据结构
- 对象的出生过程
- 为对象实例分配内存的方式
- 垃圾回收算法及机制
2.2 运行时的数据结构
来看另外一组图
程序计数器
线程私有 生命周期同线程相同
字节码文件的行号解释器,通过它指定由哪一行代码运行,同样可以实现循环、跳转
但是这是线程私有的,在多线程环境下每个线程执行的字节码文件行号是不一样的
虚拟机栈
线程私有 生命周期同线程相同
字面上看,它是一个栈的数据结构
- 每个方法被执行的时候,虚拟机会同步创建一个
栈帧
- 栈帧存放了 局部变量表、操作数栈、动态链接、方法出口等信息
- 调用时入栈,用完出栈
文章目录 |
---|
运行时栈帧结构_xtayfjpk的专栏-CSDN博客 |
本地方法栈
线程私有 生命周期同线程相同
运行非Java的Native方法,例如fork线程
堆区
基本作用
- 存放对象实例
- 受GC堆管理
- 其中又有
新生代
和老年代
的说法
文章目录 |
---|
Java中的新生代、老年代、永久代和各种GC 博客园 (cnblogs.com) |
方法区
- 存储已被加载的类型信息、常量、静态变量等
- 原先永久代使用JVM的内存,现在替换成元空间使用本地内存
- Jdk 8后方法区的字符串常量池给了堆区
运行时常量池
文章目录 |
---|
java虚拟机:运行时常量池 - xiaotian15 - 博客园 (cnblogs.com) |
直接内存
直接内存并不属于JVM的内存结构,它是物理机的内存,但是JVM虚拟机可以调用该部分内存
文章目录 |
---|
JVM中的直接内存_麦田里的守望者-CSDN博客 |
后期有空的时候要通过做实验观察一下JDK17
2.3 垃圾回收
对象的出生到死亡,从类加载到GC的回收的心路历程
对象的回收判断算法
- 引用计数算法
- 可达性分析算法
- 引用链判断
- …
垃圾收集算法
- 清除算法
- 复制算法
- 整理算法
- …
垃圾收集器
文章目录 |
---|
Jvm垃圾回收器(终结篇) - 不二尘 - 博客园 (cnblogs.com) |
2.4 JVM的参数设置
文章目录 |
---|
JVM系列三:JVM参数设置、分析 - redcreen - 博客园 (cnblogs.com) |
2.5 堆内存快照
可以用JProfiler进行分析
2.6 Java对象实例结构
对象头、对象体、对齐字节
对象头
对象体
对齐字节
2.7 JVM对象访问
-
句柄访问
如果使用句柄访问的话,那么Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息
-
直接指针
使用直接指针访问,那么Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而reference中存储的直接就是对象地址
这2中对象的访问方式各有优势,使用句柄访问方式的最大好处就是reference中存储的是稳定的句柄地址。
而使用直接指针的最大好处就是速度更快。
三、排障工具的使用
3.1 概括
故障处理工具
基础工具
安全工具
国际化
远程方法调用
Corba
java IDL、RMI-IIOP
部署工具
3.2 JVisualVM && Graalvm
Graalvm-ce-java8-21.2.0
相当于把JDK中基本的排障工具进行组合,更加方便的一个可视化工具
跟Jconsole差不多,但是它可以引入插件
3.3 JProfiler
贵死了,正版授权499美元
可以用来分析DUMP日志
四、字节码文件与类加载
描述类文件结构/类加载
4.1 Class类文件结构
-
魔数
每个Class头4个字节被称为魔数,用来确定这个文件是不是能被JVM虚拟机接受的类文件
例如这个文件存储的版本号魔数是B,但是JVM只能执行A版本的Class文件
-
常量池
字面量 and 符号引用
-
访问标志
说明这类的信息,例如:是否是public,是否是接口,是否是final
-
索引、属性、方法、字段等
4.2 字节码指令
通过将指令放在虚拟机操作数栈,指令执行进行入栈和出栈
4.3 类的生命周期
4.4 类的加载过程
加载
- 通过
类的全限定名
来获取定义这个类的二进制流
- 把字节流静态存储结构,转换为,方法区数据结构,通过
类加载器
加载到方法区中 - 在内存生成这个类的Class对象,作为方法区这个类的各种数据访问入口
验证
连接阶段的第一步,验证字节流中的信息是否符合规范
准备
为类中定义的变量(静态变量
)分配内存,这些变量所使用的内存都在方法区进行分配
解析
JVM将常量池内的符号引用替换为直接引用的过程
直接引用的实现跟虚拟机的内存布局相关,直接引用是可以直接指向目标的指针
初始化
4.5 类加载器
public abstract class ClassLoader
类加载器直接决定了比较两个类是否“相等”,由不同类加载器加载的类是必然
不相等的
例如通过应用类加载器和自定义类加载器加载同一个类,equal()方法出来都不会相同
双亲委派模型的工作过程
- 如果一个类加载器收到了类加载请求,它首先不会自己去加载,而是抛给父类加载器,层层往上抛,跑到老祖宗加载器
- 类加载是通过类的全限定名进行加载的,如果父类加载器在它搜索范围内没有这个类,就从上往下抛给儿子加载
- 这么做的好处是,有一个优先级的层次关系,并且如果过多的类加载器加载的类不会显得混乱
- 类加载请求的前提是,会先判断这个类有没有被加载过
4.6 破坏双亲委派模型&&线程上下文类加载器
文章目录 |
---|
(14条消息) 双亲委派模型与线程上下文类加载器_Rico’s Blogs-CSDN博客 |
五、字节码执行引擎
文章目录 |
---|
深入理解JVM字节码执行引擎_疯一样的女子-CSDN博客 |
六、前端编译优化 && 后端编译优化
1
我裂开,不是我现阶段该学的东西
1