虚拟机类加载机制

来源:互联网 发布:战天堂翅膀进阶数据 编辑:程序博客网 时间:2024/06/06 10:48

代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,确实编程语言发展的一大步。

虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的java类型,这就是虚拟机类加载机制。类型的加载和连接过程都是在程序运行期间完成的,这样会在类加载时稍微增加一些性能开销,但提高了灵活性。例如如果编写一个使用接口的应用程序可以等到运行时在指定其具体的实现,这种组装应用程序的方法广泛应用于java程序之中。

类加载时机
类从被加载到虚拟机内存开始,到卸载出内存为止,生命周期包括:
这里写图片描述
解析过程有时会发生在初始化之后,是为了支持java的动态绑定。

加载

类加载的一个阶段,虚拟机需要完成:
通过一个类的全限定名来获取定义此类的二进制字节流;
通过这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
在堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口。

验证

为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,且不会危害虚拟机自身的安全。(不符合则抛出java.lang.VerifyError异常或其子类异常)
四个阶段的验证过程:文件格式验证、元数据验证、字节码验证和符号引用验证。

准备

正式为类变量分配内存并设置类变量(static)初始值的阶段,这些内存都将在方法区中进行分配。这里的初始值通常是数据类型的零值,因为这个阶段尚未开始执行java方法。赋值过程会放在初始化阶段完成。static final在准备阶段就会被初始化为指定值(定义时就赋值的宏变量)。

解析

将常量池内的符号引用直接替换为直接引用。
符号引用(Symbolic Reference)以一组符号来描述所引用的目标,可以是任何形式的字面量,与虚拟机实现的内存布局无关,引用的目标不一定已经加载到内存中。
直接引用(Direct Reference)可以是直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。与虚拟机的内存布局相关,同一符号引用在不同虚拟机实例上翻译出来的直接引用一般不同,如果有了直接引用,那么引用的目标必定在内存中存在。
解析动作主要针对类或接口、字段、类方法、接口方法四类 符号引用进行。

初始化

类加载最后一步,开始执行java代码。
初始化时机:
严格规定有且只有四种情况必须对类进行初始化:
遇到new、getstatic、pubstatic或invokestatic时,如果类没有进行初始化,则必须先触发初始化(前四个步骤也必须执行) 使用new关键字实例化对象、读取或设置一个类的静态字段(被final修饰、编译期把结果放入常量池的静态字段除外)、调用一个类的静态方法;
使用java.lang.reflect包的方法对类进行反射调用时;
初始化一个类,其父类还没有初始化时;
虚拟机启动时,用户需要指定一个主类(包含main方法),先初始化这个类。

类加载器
这里写图片描述

双亲委托机制:启动类加载(Bootstrap ClassLoader \lib),拓展类加载(Extension ClassLoader \lib\ext),应用程序类加载(Appcation ClassLoader ClassPath)
双亲委托机制对于保证java程序的稳定运作很重要,实现却很简单。java.lang.ClassLoader.loadClass()。

0 0