虚拟机类加载机制

2017-03-09  本文已影响0人  Lutyison

1、类加载时机

类生命周期

加载(loading)、验证(Verification)、准备(preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸载(Unloading)
其中,验证、准备、解析统称为链接(linking)

加载时机

1、遇到new、getstatic、pustatic、invokestatic这4个字节码指令,常见场景:new实例、读取或设置一个类的静态字段、以及调用一个类的静态方法;
2、使用java.lang.reflect包的方法对类进行反射调用;
3、初始化一个类,如果其父类还没有初始化时;
4、虚拟机启动,用户需要指定一个要执行的主类(包含main()方法的类);
5、使用JDK1.7动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果时REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个句柄所对应的类没有进行过初始化时,需要先触发其初始化.

被动引用

上述情况被称为主动引用,除此之外,所有引用类的方式都不会触发初始化称为被动引用。
书中列举三种情况:
1、通过子类引用父类的静态字段,不会导致子类初始化;
2、通过数组定义来引用类,不会触发此类的初始化;
3、常量在编译阶段会存入调用类的常量池,本质上并没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化。

2、类加载过程

加载

流程,完成三件事:

验证

1、文件格式验证:
2、元数据验证
3、字节码验证

对类的方法体进行校验分析,主要目的是通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。如:

4、符号引用验证

虚拟机将符号引用转化为直接引用时,对类自身以外(常量池中的各种符号引用)的信息进行匹配性校验:

准备

正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区进行分配。仅包括类变量(被static修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在java堆中。其次,都是初始化数据类型的零值。

解析

解析是虚拟机将常量池内的符号引用替换为直接引用的过程。
解析主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用限定符7类符号引用进行。

初始化

通过程序指定的主观计划去初始化变量和其他资源,从另一个角度讲:初始化是执行类构造器<clinit>()方法的过程

3、类加载器

虚拟机外部实现类加载阶段地“通过一个类的全限定名来获取描述此类的二进制字节流”的代码模块,称为类加载器。

类与类加载器

判断两个类是否“相等”,只有在这两个类由同一个类加载器加载的前提下才有意义。这里的相等包括equals()方法、isAssignableFrom()方法、isInstance()方法的返回结果,及instanceof关键字做对象所属关系判断等情况。

双亲委派模型

类加载器(前三种为系统提供的类加载器):
双亲委派模型

类加载器收到类加载请求,先委派给父类加载器完成,层层网上,如果顶层父类加载器无法加载,子类再尝试加载。保证如java.lang.Object等基础类唯一性,使java类与类加载器一起具备带有优先级的层次关系。

破坏双亲委派模型
上一篇下一篇

猜你喜欢

热点阅读