我们使用一个类的时候,需要把这个类的class文件(又叫做字节码文件)加载到内存的方法区中,然后当我们使用的时候,JVM会将这个文件解析描述成一个class对象,通过这个对象,我们可以知道这个类中的成员变量,构造方法,成员方法等信息。这个将文件解析为虚拟机可以直接使用的对象的这个机制,就是虚拟机的类加载机制。
类加载机制
类加载机制的流程:
当程序要使用某个类的时候,如果该类还没有被加载到内存中,则系统会通过加载、连接、初始化三个步骤对该类进行初始化操作。
①加载:查找和导入class文件
类加载是指将类的class文件加载到内存中,并为之创建一个java.lang.Class对象,常称之为字节码对象。
②连接:把这个类的二进制数据合并到java运行环境中JRE中。
这里分为三步:
①:验证:检验被加载的类是否有正确的结构
②:准备:负责为类的static变量分配内存,并设置默认值
③:解析:把类的二进制数据中的符号引用替换为直接引用(符号引用是用一串字符来描述这个类的所有信息,经过虚拟机的解析,把这些符号处理成这个类的地址,再从这个地址来读取这个类的真实的所有信息),这里会把静态变量进行初始化,但是赋值是0,真正的赋值会在下一步初始化中进行,成员变量会随着对象在堆中进行初始化。
③初始化:在这个阶段,JVM会对类中静态变量进行初始化
分为以下几个步骤:
①如果该类没有被加载和连接,则先加载和连接
②如果直接父类没有被初始化,先初始化直接父类
③如果类中有初始化语句(静态代码块),则系统会在这个时候执行
进行类加载的时机:
- 使用new关键字进行实例化对象
- 操作类的静态变量
- 调用类中的静态方法
- 有子类继承,子类初始化
- 包含main方法
- 用户使用java.exe命令
- 使用反射进行功能解剖
类加载器ClassLoader
类加载器
- 上面类加载的这个过程是由类加载器完成的,这里的ClassLoader就是来进行动态的加载class文件进入到JVM并且转换为java.lang.Class类的一个实例
- 程序在启动的时候,不是一次性的把所有的class文件全部加载进去,根据程序的需要在某些时机(上面说的那些)进行动态的加载
- 类加载器通常由JVM提供,JVM启动的时候会形成用三个类加载器组成的初始类加载器层次结构。也可以自己进行定义
类加载器的分类
- bootstrap ClassLoader :根类加载器/引导类加载器:核心类的加载,比如System,String等,这个不是ClassLoader子类,由C/C++编写
- Extension ClassLoader:扩展类加载器:负责JRE中jar包的加载
- System ClassLoader:系统类加载器/应用类加载器:加载我们自己写的程序中JVM编译生成的.class文件和导入的包
可以通过静态方法ClassLoader.getSystemClassLoader()找到该类加载器。如果没特别指定,则用户自定义的任何 类加载器都将该类加载器作为它的父加载器。