一、类的加载过程
综述:
1.加载
2.连接
(2.1)验证
(2.2)准备
(2.3)解析
3.初始化
1. 加载(二、类的加载器class的作用)
- 一、ClassLoader类加载器的作用:
- 将编译器生成的.class文件加载到内存中,
- 将硬盘中的静态数据转化为内存中方法区的动态数据
就是下图的过程.classLoader
2. 链接(2.2准备
很重要)
2.1.验证(就是判断编译是否能通过.)
(1)保证加载进来的字节流符合JVM的规范,不会造成安全错误
(2)验证文件格式:比如常量final中是否有不支持的常量,文件是否规范
(3)验证元数据:是否有继承被final修饰的类(有就报错error),类中的字段,方法是否和父类冲突,是否出现不合理的重载Override
(4) 对字节码的验证,保证程序语义的合理性,比如保证转换类型的合理(比如 int 赋值给 short 就报错)
(5)对符号引用的 验证,
2.2.准备(重要
!)
(1)给类变量(static修饰的)(不是实例变量非static修饰)分配内存**(方法区
),初始化默认值(private static int age = 0 )
类变量实例变量局部变量的区别
(2)方法区
(3)常量:常量储存在方法区,且默认值为自定的值
**(private static final float PI = 3.14f)
2.3.解析(将常量池中的符号引用替换为直接引用)
(1)符号引用:就是 final float PI 中的 PI 就是符号
(2)直接引用:final float PI 的 PI的方法区的地址2341410x 就是直接引用
(3)解析阶段,JVM会吧所有的类名,方法名,字段名,的符号引用替换为内存地址的直接引用。
3.初始化 (重要)
只对static修饰的变量、或者static修饰的代码块{}构造代码块、初始化(private static int age = 18)
- 初始化一个类的时候能如果父类没有初始化,就先初始化父类
- 如果同时多个静态代码块(构造代码块)或者静态变量 按顺序 初始化.
注意区别构造函数 Person() 的初始化是在 运行期间 new 的时候 初始化实例的 ,这个static 构造代码块的初始化是在 类加载的时候运行的 .
二、什么是类加载器ClassLoader?
https://blog.csdn.net/xyang81/article/details/7292380
1. 作用
* 一、ClassLoader类加载器的作用:
* 1. 将编译器生成的.class文件加载到内存中,
* 将硬盘中的静态数据转化为内存中方法区的动态数据
2.上图
哪个红里透绿的就是类加载器ClassLoader了
3.类的缓存机制
* 二、类的缓存机制:
* 1. 标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,
* 它将维持一段时间,(缓存)不过就JVM的垃圾回收机制可以回收这些Class对象。
* `
三、类加载器的分类:
1. 分类3
名称 | 负责 | 可访问 |
---|---|---|
启动类加载器(Bootstrap) | 将Java_home/lib的类库加载(比如rt.jar)加载到内存, | 使用C/C++编写时JVM的一部分,不能访问 |
拓展类加载器(Extension) | 将lib/ext 或者系统变量 java.ext.dir 指定的位置中的类库加载到内存中, | 外部加载器使用Java编写,可以访问 |
应用加载器(Application) | 负责将Classpath 的类(通常为自定义的类)加载到类库,因为这个类的加载器是getSystemCalssLoader()方法的返回值,所以也叫系统类加载器(System) | Java 编写,可访问 |