天天看点

bootstraptable treeGrid 懒加载_jvm之java类加载机制和类加载器(ClassLoader)

当程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载、连接、初始化3个步骤来对该类进行初始化。如果没有意外,JVM将会连续完成3个步骤,所以有时也把这个3个步骤统称为类加载或类初始化。

bootstraptable treeGrid 懒加载_jvm之java类加载机制和类加载器(ClassLoader)

一 类加载机制

1.1 加载

加载主要是将.class文件(并不一定是.class。可以是ZIP包,网络中获取)中的二进制字节流读入到JVM中。

在加载阶段,JVM需要完成3件事:

1)通过类的全限定名获取该类的二进制字节流;

2)将字节流所代表的静态存储结构转化为方法区的运行时数据结构;

3)在内存中生成一个该类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

1.2 连接

1.2.1 验证

验证是连接阶段的第一步,主要确保加载进来的字节流符合JVM规范。

验证阶段会完成以下4个阶段的检验动作:

1)文件格式验证

2)元数据验证(是否符合Java语言规范)

3)字节码验证(确定程序语义合法,符合逻辑)

4)符号引用验证(确保下一步的解析能正常执行)

1.2.2 准备

准备是连接阶段的第二步,主要为静态变量在方法区分配内存,并设置默认初始值。

1.2.3 解析

解析是连接阶段的第三步,是虚拟机将常量池内的符号引用替换为直接引用的过程。

1.3 初始化

初始化阶段是类加载过程的最后一步,主要是根据程序中的赋值语句主动为类变量赋值。

注:

1)当有父类且父类为初始化的时候,先去初始化父类;

2)再进行子类初始化语句。

什么时候需要对类进行初始化?1)使用new该类实例化对象的时候;

2)读取或设置类静态字段的时候(但被final修饰的字段,在编译器时就被放入常量池的静态字段除外static final);

3)调用类静态方法的时候;

4)使用反射Class.forName(“xxxx”)对类进行反射调用的时候,该类需要初始化;

5) 初始化一个类的时候,有父类,先初始化父类(注:1. 接口除外,父接口在调用的时候才会被初始化;2.子类引用父类静态字段,只会引发父类初始化);

6) 被标明为启动类的类(即包含main()方法的类)要初始化;

7)当使用JDK1.7的动态语言支持时,如果一个java.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。

以上情况称为对一个类进行主动引用,且有且只要以上几种情况需要对类进行初始化。

二 类加载器

类加载器实现的功能是即为加载阶段获取二进制字节流的时候。

JVM提供了以下3种系统的类加载器:

  • **启动类加载器(Bootstrap ClassLoader):**最顶层的类加载器,负责加载 JAVA_HOME\lib 目录中的,或通过-Xbootclasspath参数指定路径中的,且被虚拟机认可(按文件名识别,如rt.jar)的类。
  • **扩展类加载器(Extension ClassLoader):**负责加载 JAVA_HOME\lib\ext 目录中的,或通过java.ext.dirs系统变量指定路径中的类库。
  • **应用程序类加载器(Application ClassLoader):**也叫做系统类加载器,可以通过getSystemClassLoader()获取,负责加载用户路径(classpath)上的类库。如果没有自定义类加载器,一般这个就是默认的类加载器。

类加载器之间的层次关系如下:

bootstraptable treeGrid 懒加载_jvm之java类加载机制和类加载器(ClassLoader)

继续阅读