- 总共七个过程:加载——验证——准备——解析——初始化——使用——销毁
- 加载:通过一个类的全限定名获取此类的二进制字节流。将这个字节流代表的静态存储结构转化为方法区的运行时数据结构。在内存中生成一个Java.lang.Class对象,作为方法区这个类的各种数据的访问入口
- 验证:用于验证此类文件的字节流包含的信息是否符合Java虚拟机规范,不会危害虚拟机自身安全。验证包括文件格式验证、元数据验证、字节码验证、符号引用验证。
- 准备:正式为类变量分配内存并设置类变量初始化的阶段。这个阶段进行内存分配的仅包括类变量(static修饰的变量),不包括实例变量,实例变量会在对象实例化时跟着对象一起分配在Java堆中。在这里说的类变量初始化也只是指将这个变量的数据类型的零值。
- 解析:虚拟机将常量池内的符号引用替换为直接引用的过程。直接引用指的是直接指向目标的指针、相对偏移量或者是一个能间接定位到目标的句柄。
- 初始化:执行构造器<clinit>()方法的过程。首先clinit方法是编译器自动收集类中的所有类变量的赋值动作和静态语句块中的语句合并产生的。静态语句块只能访问到定义在静态语句块之前的变量定义之后的变量,在前面的静态语句块中可以赋值,但是不能访问。父类的clinit方法执行之后才能执行子类的方法。
类加载器
- 定义:Java通过一个类的全限定名来获取描述此类的二进制字节流这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类,实现这个动作的代码称为“类加载器”。
- 类加载器作用:由加载它的类加载器和这个类本身异同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。举例来说,判断两个类是否相等,是指在同一个类加载器的前提下才有意义,否则这两个类永远都不相等
- 加载器类型:Java虚拟机只有两种不同的类加载器。一种是启动类加载器,这个类加载器由C++语言实现,另一种就是其他的类加载器,这些类加载器都由Java语言实现,独立于虚拟机外部,全部继承自java.lang.ClassLoader。根据层次划分,可以划分为启动类加载器、扩展类加载器、应用程序类加载器。
- 双亲委派模型:除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。这里类加载器之间的父子关系一般不会以继承的关系来实现,而是都使用组合关系来复用父加载器的代码。