JAVA类的生命周期与加载机制
一.类的生命周期
加载->验证->准备->解析->初始化->使用->卸载
二.加载类的场景
1.遇到new,getstatic,putstatic或者invokestatic这四个指令的时候出发初始化
2.使用java.lang.reflect包中的方法进行反射调用的时候,如果类没有经过初始化过则一定触发其初始化
3.初始化子类,但父类没有初始化,那么一定初始化父类
4.虚拟机启动,用户指定执行的主类(包含main方法的类)
三.类加载的过程
A.通过一个类的全限定名来获取定义此类的二进制字节流
B.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
C.在内存中生成一个代表这个类的class对象,作为方法区这个类的各种数据的访问路口
四.验证
文件格式的验证:验证格式是否安全
元数据的验证:验证是否符合java语言的规范,比如数据类型的校验
字节码验证:通过数据流和控制流分析,确定程序语言是合法的,符合逻辑的,主要是对类的方法体进行验证
五.准备
正式为类变量分配内存并设置类变量初始值零值
PS:
1.只是赋零值,而不是初始化赋值 比如 public static int count = 123; 经过这个阶段之后是0 在经过初始化之后才是123
2.这个只是为类变量进行分配(被static修饰) 实例变量将在实例化的时候分配在java堆中
六.解析
将常量池内的符号引用替换为直接引用
符号引用:一些描述的字面量,比如类文件中的字符,符号可以直达到引用的目标即可
直接引用:直接指向目标的指针,相对偏移量或者能间接定位目标的句柄
在这个过程中包含:类或接口的解析,字段解析,方法解析
七.初始化:真正开始执行类中定义的java代码
执行类构造器方法的过程
该方法是自动收集类中的所有类变量的赋值以及静态语句块的操作
由于父类先初始化,父类的赋值会先于子类的赋值
八.类加载器作用
任何一个类,都需要由加载他的类加载器和这个类本身来一同确定这个类的唯一性
即使一个类是源于同一个class文件,被同一个虚拟机加载,只要类加载器不同 那么两个类就不相等
类加载器分为两种: 1.启动类加载器(Bootstrap ClassLoader) 这个类加载器使用C++实现,是虚拟机自身的一部分
2.其他的所有类加载器.由java实现,独立于虚拟机外部,且全部继承自java.lang.ClassLoader
双亲委派模型:
要求:除了顶层的启动类加载器之外,其余的类加载器都应该有自己的父类加载器,
工作流程:一个类加载器收到了类加载的请求,首先自己不会尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个诚实的类加载器都是这样,因此所有的类都会传递到顶层的启动类加载器中
当父类无法完成加载请求,子类才会尝试加载 比如Object类,在各种类加载器环境中都是一个类,因为最终会传递到Object类以及Object类的加载器上 这样
优势:
1.由于是父类先加载,那么类加载器就有了一定的层级关系,可以避免类的重复加载,比如 A,B的父类都是C 那么当A加载的时候已经加载了C 那么B的时候就不需要加载了
2.保证JAVA API中的类不会被随意篡改