类加载器【JVM】
JVM-类加载器1. 类加载系统作用:类加载系统的主要作用就是将编译生成的字节码文件加载到内存,当然此处的字节码文件可以存在磁盘或网络等其它地方。主要过程:加载链接初始化1.1 加载过程加载过程主要把磁盘或网络中其他形式的字节码加载到内存中, 并且在内存中生成Class对象1.2链接过程验证主要用于验证当前字节码文件是否满足虚拟机的格式, 比如class文件在文件开头都有CA FE BA BE这几
·
JVM-类加载器
1. 类加载系统
- 作用:类加载系统的主要作用就是将编译生成的字节码文件加载到内存,当然此处的字节码文件可以存在磁盘或网络等其它地方。
- 主要过程:
- 加载
- 链接
- 初始化
1.1 加载过程
- 加载过程主要把磁盘或网络中其他形式的字节码加载到内存中, 并且在内存中生成Class对象
1.2链接过程
- 验证
- 主要用于验证当前字节码文件是否满足虚拟机的格式, 比如class文件在文件开头都有CA FE BA BE这几个十六进制数据,如果没有就说明字节码文件有问题
- 准备
- 准备阶段主要对字段的静态变量赋一个初始值,但真正的值是在初始化过程中执行的;这些静态字段的存储一般是方法区,但不同版本JDK存储静态变量的地方不同
- JDK6:直接存储静态变量在永久代
- JDK7:永久代存在,但是将静态变量存储在堆中(也包括字符串常量)
- JDK8:永久代不存在了,永久代存放在直接内存,而字符串常量和静态常量还是存放在堆
- 准备阶段主要对字段的静态变量赋一个初始值,但真正的值是在初始化过程中执行的;这些静态字段的存储一般是方法区,但不同版本JDK存储静态变量的地方不同
- 解析
- 将符号引用转为直接引用,因为在编译阶段还无法确定引用的某一个对象的地址所以使用的是符号引用;但是在加载到内存的时候就必须知道引用的对象的地址,在此处也就是真正的解析为地址
1.3初始化过程
实际上在初始化过程中执行的是一个自动生成的方法,该方法中包含了静态变量的初始化以及静态代码块, 并且该方法是线程安全的,可以在static代码块儿中写个死循环然后然两个线程去加载看测试效果
-
自动执行所有的赋值过程
-
执行静态代码块儿
-
以上两者的执行顺序是由在源文件中的编写顺序决定的(因为变量的定义早就在链接过程就做了)
public class demo{ static { num = 10; sout(num);//报错, 非法的前向引用,可以修改不可以打印 } private static int num = 20; public static void main(String[] args) { sout(num);//20 } }
2. 类加载器
-
定义:
- JVM默认有两个类型的类加载器,包括:引导类加载器,以及自定义类加载器; 因为在JVM中只要是派生于ClassLoader接口的类加载器都是自定义类加载器
-
默认类加载器
- BootStrap Class Loader【不是java语言实现】
- 加载系统的核心类库
- 无法获取到,如:你使用String去获取类加载器是null
- Extention Class Loader
- 被引导类加载
- 加载jre/lib/ext下的类
- System Class Loader
- 被引导类加载
- BootStrap Class Loader【不是java语言实现】
-
默认主动加载情况
在以下情况会执行clinit方法
- 创建类实列
- 访问某个类或接口的静态变量
- 调用类的静态方法
- 反射
- 初始化一个类的 子类
- java虚拟机启动时被标注为启动类的类
3.自定义类加载器
- 用途
- 隔离加载类【这就是为什么spring,Tomcat会自定义类加载器, 因为不通框架可能存在路径名称一致的情况】
- 扩展加载源
- 修改加载方式
- 防止源码泄露
4.双亲委派机制
- 如果一个加载器收到了一个加载类的需求,那么他不会立即去加载当前类,而是先委托父类的加载器去执行;如果父类加载器能够完成类加载就直接返回,如果父类都不能加载才让子类加载器去加载
- Boot Class Loader
- 加载java.xxx.xx
- javax.xx.xx
- 如何判断两个Class对象是否为同一个
- 包名类名相同
- 同一个类加载器
5. jclasslib插件(idea)可以查看字节码
- 如以下是方法的字节码
更多推荐
所有评论(0)