一、原理
1.jdk>jre>jvm
2.java->class->jvm->操作系统
3.类加载机制
3.1装载:class->二进制字节流。通过全限定名获取二进制字节流(外部实现,类加载器来实现)
3.2验证:
- 元数据验证(本类的验证)
- 字节码验证(jvm安全验证)
- 符号引用验证(引用的其他类是否存在等)
取消验证,可以在idea中配置jvm参数
-Xverify:none
3.3准备:为类的静态变量(类变量)分配内存及零值(默认初始值)
//类变量在准备阶段完成后,a=0,保存在方法区中
private static int a=1;
//实例变量不会准备阶段进行内存分配,会随着实例对象,一起分配到java堆中
private int b=2;
//类变量被final修饰符修饰后,在准备阶段完成后,c=3。
private final static int c=3;
ConstantValue:当final static修饰时才会有ConstantValue;通知虚拟机自动为类变量赋值;仅支持基本类型和String,因为常量池仅能引到基本类型和String。
扫描二维码关注公众号,回复:
13457818 查看本文章
3.4解析:符号引用转换为直接引用
直接引用的目标一定在内存空间上,符号引用则不一定
invokedynamic指令,动态解析,应用于lamda表达式,jdk7引入,jdk8开始使用
3.5初始化 Clinit
类变量初始化:指令类变量;静态代码块(静态代码块要在类变量声明之后)
3.6使用:
- 类初始化的触发:主动使用
- 被动引用:访问静态变量、定义某个类的数组、访问常量
3.7卸载(非常少,2、3很难满足)
4.类加载器
一个类在同一加载器中具有唯一性;不同加载器允许同名类存在
默认加载器:Bootstrap、Ext、Application
类加载器机制的三种方式
- 全盘负责(当前类加载器),类加载器加载某个类时,该类所依赖和引用的其它类也会使用当前类加载器进行加载。application一般会再使用父类委托进行其他类的加载;
- 父类委托(双亲委派),如果存在父类加载器则使用父来加载器加载;
- 缓存机制(自缓存),类加载后存储在内存中,如果存在则不再重复加载,类的唯一性。
二、常用命令
1.将class文件转换为可以查看的文件:
javap -p -v .\HelloWorldExample.class > a.txt