JVM的类加载机制就是:JVM把描述类的class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被JVM直接使用的Java类型
ClassLoader
JVM中的ClassLoader子系统就是类加载系统,Classloader子系统根据给定的全限定名类名(如java.lang.Object)来装载class文件的内容到运行时数据区中的方法区。Java程序员可以继承java.lang.ClassLoader类来编写自己的Class loader。
每个类都有一个Class对象,编译一个新类就回产生一个Class对象(保存在同名的.Class文件中),类加载器是生成这个Class对象的子系统
每个Class对象都有一个reference,指向自己的ClassLoader。使用Class.getClassLoader()可以获得自己的ClassLoader。ClassLoader负责将Class加载到JVM中,同时也将Class字节码重新解析成JVM统一要求的对象格式。
如何加载Class文件
类加载过程包括一下几个步骤:
- 加载
- 连接
- 初始化
- 卸载
加载
加载就是把二进制形式的Java类型读入JVM中,而连接就是把已经读入虚拟机的二进制形式的类型数据合并到虚拟机的运行时状态中去。
在加载阶段,JVM需要完成以下事情:
- 通过一个类的全名限定来获取定义此类的二进制字节流
- 将这个字符流所代表的静态存储结构转化为方法区的运行时数据结构
- 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
连接
加载阶段完成之后,JVM外部的二进制字节流按照JVM所需的格式存储在方法区中,然后在内存中实例化一个java.lang.class对象
连接可以分解为以下三步:
验证:验证Java类型数据格式的正确,是否适合JVM使用。一般包括文件格式验证、元数据验证、字节码验证、符号引用验证。
准备:分配该类型所需的内存,并设置类变量的初始值,这些变量所使用的内存都在方法区中进行分配。
解析:将常量池中的符号引用转换为直接引用。虚拟机可以在运行时的程序真正使用某个符号引用时再将其转为直接引用。包括类或接口的解析、字段解析、类方法解析、接口方法解析。
初始化
初始化是给类变量赋值,到了初始化阶段才开始真正执行类的字节码。
卸载
对象的终结:如果类声明了一个finalize()的返回void的方法,垃圾收集器会在释放之歌实例所占据的内存空间之前执行这个方法一次。