流程图

类加载过程
- 加载
- 链接
- 初始化

加载:
- 通过一个类的全限定名获取定义此类的二进制字节流‘
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构(加载后的类信息存放于方法区内)
- 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
链接
验证
确保class文件中的字节流包含的信息符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身的安全
准备
为类变量分配内存并且设置该类变量的默认初始值。
解析
将常量池内的符号引用转换为直接引用的过程。
初始化
执行类构造器方法()的过程。
类加载器的分类
启动类加载器(引导类加载器,Bootstrap ClassLoader)
- 使用c/c++语言实验
- 用于加载Java的核心类库
- 并不继承自java.lang.ClassLoader
- 加载扩展类和应用程序类加载器
扩展类加载器(Extension ClassLoader)
- 派生于ClassLoader类
- 父类加载器为启动类加载器
系统类加载器(AppClassLoader)
- 派生于ClassLoader类
- 父类加载器为扩展类加载器
- 该类加载是程序中默认的类加载器,一般来说,java应用的类都是由它来实现加载的
ClassLoader类
ClassLoader(java.lang.ClassLoader)是一个抽象类,除启动类加载器外,所有的类加载器都继承于ClassLoader类。
用户可以通过继承java.lang.ClassLoader类的方式,实现自己的类加载器,以满足自己的需求。
双亲委派机制
JVM对class文件采用的是按需加载的方式,也就是说等到需要使用该类的时候才会对它的class文件加载到内存生成class对象。而加载这个class文件时,JVM采用的是双亲委派机制。
双亲委派机制工作原理

- 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是将这个请求委托给父类的加载器去执行
- 如果父类加载器还存在其父类加载器,则进一步向上委托,执行递归操作,最终到达顶层的启动类加载器
- 如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此次加载任务,子类加载器才会尝试自己去加载,这就是双亲委派机制。
双亲委派机制的优势
- 避免类的重复加载
- 保护程序安全,防止核心API被随意篡改
沙箱安全机制
自定义String类,但是在加载自定义String类的时候会优先用启动类加载器进行加载,启动类加载器会优先加载jdk自带文件中的String类,而不是用户自定义的String类。这样可以保证对Java核心源代码的保护,这就是沙箱安全机制。
类的主动使用
Java程序对类的使用方式分为:主动使用和被动使用
主动使用分为:
- 创建类的实例
- 访问某个类和接口的静态变量,或者对改静态变量赋值
- 调用类的静态方法
- 反射
- 初始化一个类的子类
- JVM启动时被标明为启动类的类
- JDK7开始提懂得动态语言支持:java.lang.invoke.MethodHandle实例的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic句柄对应的类没有初始化,则进行初始化
以上其中对类的主动使用会导致类的初始化,其他的对类的使用方式都看作是对类的被动使用,不会导致类的初始化。