虚拟机类加载机制

 1、加载

加载阶段,虚拟机需要完成以下3件事情:

  • 通过一个类的全限定名来获取定义此类的二进制字节流
  • 将这个字节流代表的静态存储结构转化成方法区的运行时数据结构
  • 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口

2、验证

        这一阶段的主要目的是为了确保Class文件的字节流包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

2.1 文件格式验证

        验证魔数、版本号、常量池类型、指向常量的索引、utf8编码。主要目的就是保证输入的字节流能正确地解析并存储于方法区之内,格式上符合描述一个Java类型信息的要求。只有通过这个验证,才会到内存中的方法区进行存储,后续验证阶段就是基于方法区的内容,而不是二进制字节流了。

2.2 元数据验证

        对字节码的信息进行语义分析,是否有父类,是否满足继承体系(单继承,不能继承final类),字段方法等是否与父类冲突。这个阶段目的就是对类的元数据进行语义校验,保证不存在不符合Java语言规范的元数据信息。

2.3 字节码验证

        主要目的是通过数据流和控制流分析,确定程序语义的合法性,保证类的方法在运行期间不会做出危害虚拟机的行为。例如:保证任何时候操作数栈的数据类型和指令代码序列配合工作,bu不会出现用long指令加载一个int类型之类的事情。保证跳转指令不会跳到方法体以外的字节码指令上。保证类型转换是有效的,子类赋给父类变量是安全的等。这个阶段不能保证完全正确,可能会有问题。

2.4 符号引用验证

        这个阶段的校验发生在虚拟机将符号引用转化为直接引用的时候,这个转化将在第三阶段解析中发生。符号引用验证是对类自身以外的信息进行匹配校验,主要校验:能否找到对应的引用类,是否存在相关方法属性字段,是否有权限访问(private)。如果无法通过验证,会抛出java.lang.IncompatibleClassChangeError异常的子类,如IllegalAccessError、NoSuchFieldError和NoSuchMethodError等。

3、准备

        准备阶段是为类的变量分配内存,并设置类变量初始值的阶段,这些变量使用的内存,都在方法区中进行分配。注意,只包含static类变量,实例变量是在堆中的,初始值一般是数据类型的零值,比如public static int value = 123。初始值是0,而不是123。但是还有特殊情况,比如被final修饰,存在ConstantValue属性,会在准备阶段就会赋值。

4、解析

        解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。解析主要包括:

  • 类或接口的解析
  • 字段解析
  • 类方法解析
  • 接口方法解析

5、初始化

        类初始化阶段是类加载过程的最后一步,前面的类加载过程中,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码(字节码)。初始化对于类来说,就是执行类构造器<clinit>()方法的过程。

6、双亲委派模型

        应用程序都是由这3种类加载器互相配合进行加载的,如果有必要还可以加入自己定义的类加载器。这些类加载器之间的关系如下图:

        图中的层次关系,称为类加载器的双亲委派模型。双亲委派模型要求除了顶层的根类加载器以外,其余的类加载器都应该有自己的父类加载器(一般不是以继承实现,而是使用组合关系来复用父加载器的代码)。如果一个类收到类加载请求,它首先请求父类加载器去加载这个类,只有当父类加载器无法完成加载时(其目录搜索范围内没找到需要的类),子类加载器才会自己去加载。 

         这个模型的好处在于Java类有了一种优先级的层次关系。比如Object类,这个毫无疑问应该交给最上层的加载器进行加载,所以在各个类加载器环境中这个类都是同一个类。如果没有双亲委派模型,自己写一个java.lang.Object类,会出现很多个不通的Object类,应用程序会一片混乱。实现很简单,都在ClassLoader的loadClass方法之中,先检查是否被加载过,若没有加载就调用父类加载器的loadClass方法,若父类加载器为空,默认使用启动类加载器,如果加载失败,抛出异常后调用自己的findClass()方法进行加载。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值