JVM 杂记(二)
1.1 字节码技术
编译:javac demo/jvm/Xxx.java
查看字节码: javap -c demo.jvm.Xxx
JVM 是一台基于栈的计算机器
每个线程都有一个独属于自己的线程栈(Stack),用于存储栈帧(Frame),每一次方法调用,JVM会自动创建一个栈帧。
栈帧 = 操作数栈 + 局部变量数组 + Class引用(指向当前方法在运行时常量池中对应的Class)
方法调用的指令:
invokestatic:调用静态方法,最快
invokespecial:调用构造函数、同一个类中的private方法、可见的超类方法
invokevirtual:调用public、protected、package级的私有方法
invokeinterface:通过接口引用来调用方法
invokedynamic:支持lambda表达式的实现基础
1.2 类加载器
1.2.1 生命周期
加载(Loading):找 Class 文件
验证(Verification):验证格式、依赖【链接(Linking)】
准备(Preparation):静态字段、方法表【链接(Linking)】
解析(Resolution):符号解析为引用【链接(Linking)】
初始化(Initialization):构造器、静态变量赋值、静态代码块
- 父类静态变量
- 父类静态代码块
- 子类静态变量
- 子类静态代码块
- 父类非静态变量
- 父类非静态代码块
- 父类构造函数
- 子类非静态变量
- 子类非静态代码块
- 子类构造函数
首先,静态优先于非静态,其次,父类优先于子类,最后变量优先于代码块,另外,构造函数属于非静态,在代码块之后执行。
使用(Using)
卸载(Unloading)
1.2.2 不会初始化的情况(可能会加载)
通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化;
定义对象数组,不会触发该类初始化;
常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触发类初始化;
通过类名获取 Class 对象,不会触发类初始化;
通过 Class.forName 加载指定类时,如果指定参数 initialize 为 false 时,也不会触发类初始化,否则就会初始化;
通过 ClassLoader 默认的 loadClass 方法,只加载,不会初始化。
1.2.3 类加载器
启动类加载器(BootstrapClassLoader)
扩展类加载器(ExtClassLoader)
应用类加载器(AppClassLoader)
特点:
双亲委托
负责依赖
缓存加载
1.3 内存模型
Java进程组成:
栈 Stack
堆 Heap
- 年轻代 Young generation
- 新生代 Eden space
- 存活区 Survivor space:总有一个是空的
- S0
- S1
- 老年代 Old generation (进入老年代阈值
-XX:+MaxTenuringThreshold=15
)
- 老年代 Old generation (进入老年代阈值
非堆 Non-Heap:本质上还是 Heap,只是不归 GC 管理
- 元数据区 Metaspace
-XX:MaxMetaspaceSize=256m
- 元数据区 Metaspace
- 常量池
- 方法区
- CCS = Compressed Class Space:存放 class 信息,和 Metaspace 有交叉
- Code Cache:存放 JIT(just-in-time compilation 及时编译) 编译器编译后的本地机器代码
JVM自身
1.4 启动参数
-D
:设置系统属性
-X
:非标准参数,基本都是传给 JVM 的,默认 JVM 实现这些参数的功能,但是并不保证所有 JVM 都满足,也不保证向后兼容。
-XX
:非稳定参数,随时可能在下一版本取消
-XX:+Use**GC
:使用 G1/ConcMarkSweep、Serial、Parallel GC
-XX: +UnlockExperimentalVMOptions -XX:+UseZGC
:Java 11+ 有 ZGC
-XX: +UnlockExperimentalVMOptions -XX:+UseShenandoahGC
:Java 12+ 有 Shenandoah GC
分析诊断
|
|
JavaAgent
Agent时JVM中的一项黑科技,可以通过无侵入方式注入AOP代码或执行统计,权限非常大。
|
|
2.1 内置命令行工具
javap:反编译class文件
jar:打包文件或目录成.jar文件
jps:查看Java进程
jstat:查看JVM内部gc相关信息
|
|
jmap:查看heap或类占用空间统计
|
|
jstack:查看线程信息
-F
:强制执行 thread dump,可在Java进程卡死时使用
-m
:混合模式,将 Java 帧和 native 帧一起输出
-l
:长列表模式,将线程相关的locks信息一起输出,比如持有的锁,等待的锁
jcmd pid help:综合了前面几个命令
2.2 内置图形化工具
jconsole
jvisualvm
visualgc
jmc
用于对 Java 应用程序进行管理、监视、概要分析和故障排除的工具套件。
2.3 GC 原理
为什么要分代?
大部分新生对象很快无用
存活较长时间的对象,可能存活更长时间
2.4 串行/并行 GC
2.5 CMS/G1 GC
2.6 ZGC/Shenandoah GC
2.7 GC 总结
3.1 GC 日志解读与分析
|
|
3.2 JVM 线程堆栈数据分析
3.3 内存分析与相关工具
堆内存溢出
元空间溢出
本地方法栈溢出