JVM类加载机制

来源:互联网 发布:倒计时软件安卓 编辑:程序博客网 时间:2024/06/04 18:18

JVM类加载共分为七步:加载、验证、准备、解析、初始化、使用、卸载。其中验证、准备、解析这三部总称为连接。
一、加载
加载共分为三步:
1、通过Class文件(或者压缩包,例如jar包)获得二进制字节流
2、将二进制字节流的静态数据结构转化为方法区中的运行时数据结构
3、在堆中创建java.lang.Class对象作为方法区数据访问接口
这一步是JVM类加载中最重要的一步。只有两个类的类和加载这两个类的类加载器都相同,这两个类才相同。类加载器分为启动类加载器、扩展类加载器、应用程序类加载器以及用户自定义加载器。其中启动类加载用于加载%JAVA_HOME%/lib目录以及用-Xbootclasspath指定路径的文件;扩展类加载器用于加载%JAVA_HOME%/jre/lib/ext目录;应用程序类加载器用于加载用classpath指定路径的文件。启动类加载器不能直接引用使用,而扩展类加载器和应用程序类加载器可以直接引用使用。JVM加载类采用双亲委托机制,即子类不加载类而交由父类加载,直到最顶级的父类,如果父类无法加载,则交由其子类加载。这种机制保证了Object类使用不同加载器加载出的都是同一个类。
二、验证
验证主要验证二进制流中所包含的数据是否符合JVM规范,以及保证其不会危害到JVM。验证共分为文件格式验证、元数据验证、字节码验证、符号引用验证。
文件格式验证:
验证字节流是否符合Class文件规范,确保字节流能够正确写入方法区。元数据验证、字节码验证、符号引用验证都是基于方法区的存储结构进行验证
元数据验证:
验证是否有父类;
验证是够继承了不可被继承的类(final修饰的类)
验证是否实现了父类的抽象方法
验证是否覆盖了父类的不可修改的属性(final修饰的属性)
字节码验证:
主要验证类的方法体内不会产生危害JVM的结果
符号验证:
验证是否能通过类的全类名找到相应的类,验证访问修饰符的合法性
三、准备
为类变量在方法区中分配内存并赋初值,赋值为默认值,不是等号后的值,若变量被static final修饰,则在此阶段赋初值
四、解析
将常量池中的符号引用替换为直接引用,直接引用可以是指向目标的指针,相对偏移量或者能间接定位目标的句柄
五、初始化
执行java代码,初始化除在准备阶段已经赋值的变量之外的其他部分,即执行类构造器方法()