JVM 基础
目录
导图
总览
Java虚拟机运行时数据区
初识JVM
Java虚拟机的组成
字节码文件详解
正确打开字节码
字节码文件的组成
基础信息
常量池
方法
字节码常用工具的使用
类的生命周期
简介
加载阶段
连接阶段
验证
准备
解析
初始化阶段
类加载器
类加载器的分类
启动类加载器
默认加载器
双亲委派
机制
打破双亲委派机制 *
自定义类加载器
线程上线文类加载器
Osgi框架的类加载器(了解)
JDK9之后的类加载器
总结
运行时数据区
程序计数器
栈
局部变量表
操作数栈
栈内存溢出
堆内存
方法区
实现
字符串常量池
直接内存
总结
自动垃圾回收
介绍
方法区的回收
堆回收
引用计数法和可达性分析法
五种对象引用
软引用
弱引用
虚引用和终结器引用
垃圾回收算法
评价标准
标记回收算法
复制算法
标记整理算法
分代垃圾回收算法-GC算法*
垃圾回收器
预热
Serial 垃圾回收器
年轻代 PaNew 垃圾回收器
老年代 CMS 垃圾回收器
年轻代 Parallel Scavenge 垃圾回收器-JDK8默认
老年代 Parallel Old 回收器-JDK8默认
G1 垃圾回收器-JDK9默认
导图
总览
初识JVM
然后将字节码交给计算机执行
Java虚拟机的组成
字节码文件详解
正确打开字节码
jclasslib工具的Github地址: https://github.com/ingokegel/jclasslib
字节码文件的组成
基础信息
常量池
方法
字节码常用工具的使用
Arthas功能很强大,具体功能和命令可到官网查看
Arthas(阿尔萨斯)官网文档:https://arthas.aliyun.com/doc/
类的生命周期
简介
加载阶段
在代码使用反射获取对象信息就是在方法区中拿的
方法区中的 InstanceKlass 是C++编写的,无法Java语音调用,在堆区中转成Java类型的;
每个类在方法区和堆区中都分别对应一个 InstanceKlass 对象和 java.lang.Class
对象;
InstanceKlass保存类的元数据,java.lang.Class
对象是根据InstanceKlass生成的,是一个简化版的 InstanceKlass(去除了一些对开发者无用的元数据)
连接阶段
验证
准备
解析
初始化阶段
静态块在类被加载时执行,并且只执行一次,输出D
main方法执行第一行,输出A
初始化类Test1,先执行其他代码块后执行构造方法,输出CB
又初始化类Test1,先执行其他代码块后执行构造方法,输出CB
类加载器
类加载器的分类
启动类加载器
默认加载器
双亲委派
机制
其实就是自底向上查找是否加载过,自顶向下加载
打破双亲委派机制 *
自定义类加载器
线程上线文类加载器
DriverManager 是JDK提供的
Osgi框架的类加载器(了解)
JDK9之后的类加载器
总结
运行时数据区
程序计数器
随着线程被销毁,线程不共享的内存也会被释放
字节码指令写字节码文件中,当文件被加载之后字节码指令就会被保存在内存中,而程序计数器就算记录下一次执行的字节码指令所在的内存地址
栈
局部变量表
操作数栈
栈内存溢出
一般建议使用 -Xss 的方式设置
堆内存
方法区
实现
InstanceKlass 对象中的常量池和方法其实会额外开辟一个内存来存储,InstanceKlass对象只是存放了引用
字符串常量池
a + b 底层是 StringBuilder ,结果对象存放在堆中,所有上述代码结果是 false
而 "1" + "2" 在编译阶段会直接将其替换为 "12" , 而 "12" 在常量池冲存放,所有运行结果我 true
直接内存
当 jvm正在回收堆中对象的时候,如果用户正在使用我们的系统,可能会出现卡顿的情况
总结
1、程序计数器:每个线程会通过程序计数器记录当前要执行的的字节码指令的地址,程序计数器 可以控制程序指令的进行实现分支、跳转、异常等逻辑(不会出现内存泄漏)。
2、虚拟机栈:虚拟机栈采用栈的数据结构来管理 方法调用中的基本数据(局部变量、操作数等), 每一个方法的调用使用一个栈帧来保存。
3、堆:堆中存放的是创建出来的对象,这也是最容易产生内存溢出的位置。
4、方法区:方法区中主要存放的是类的元信息,同时还保存了常量池,JDK8是使用了元空间, 保存在直接内存。
自动垃圾回收
介绍
方法区的回收
堆回收
引用计数法和可达性分析法
五种对象引用
软引用
弱引用
虚引用和终结器引用
垃圾回收算法
评价标准
标记回收算法
复制算法
标记整理算法
分代垃圾回收算法-GC算法*
这个年轻代的GC用的是复制算法,这个S0和S1统称Survivor区
垃圾回收器
预热
Serial 垃圾回收器
年轻代 PaNew 垃圾回收器
老年代 CMS 垃圾回收器
只有在初始标记和重新标记中用户线程会停下来,且时间非常短
年轻代 Parallel Scavenge 垃圾回收器-JDK8默认
老年代 Parallel Old 回收器-JDK8默认
G1 垃圾回收器-JDK9默认
G1 垃圾回收器在 jdk8 相对成熟,但仍有不足之处,在 jdk9 中得到完善