我看Java虚拟机(5)---虚拟机加载机制

经过上节的讲解,我们已经知道了Java代码——》字节码的过程,产生了字节码,下一步就是将字节码读入虚拟机,虚拟机将该部分分为七个步骤:
加载->验证->准备->解析->初始化->使用->卸载
我们主要研究前5步。

加载

  • 读入二进制字节流,并不限定是class文件,可以是zip,jar,网络获取或者其他。
  • 将字节流代表的静态结构转换为方法区的运行时数据结构
  • 在堆中创建代表这个类的java.lang.class对象,作为方法区这些数据的访问入口

验证

  • 文件格式验证,由于虚拟机只规定了读入的是二进制字节流,并未规定必须是class文件,所以有可能是恶意的二进制流,为了防止其破坏虚拟机,所以对其文件格式进行验证:魔数是否0xCAFEBABE开头,主次版本等。
  • 元数据验证,对类的元数据信息进行语义进行校验,保证不存在不符合Java规范的元数据。是否有父类,是否为抽象类,是否实现了接口或父类要求实现的方法等
  • 字节码验证,最复杂的一步,数据流和控制流分析。
  • 符号引用验证,解析阶段发生,将符号引用转换为直接引用。

准备

为类变量赋初始值,但并不是为其赋真正的值,比如:

public static int a = 1;

该步为a在方法区分配空间,并赋值为0,特殊的final:

public static final int a = 1;

则该步将直接给a赋值为1

解析:

符号引用:以一组符号来定位所引用的目标。
直接引用:直接指向目标的指针,相对偏移量或者能间接定位到目标的句柄。
针对类或接口,字段,方法,接口方法四类符号进行解析,将符号引用转换为直接引用。

初始化:

以下四种方式会触发类的初始化:

  • 使用new,引用类static变量,static方法,除了final修饰的字段和方法。
  • 使用reflect进行反射调用
  • 父类
  • main方法所在的类,启动类

书中还介绍了类加载器相关内容,其中实例练习也是关于此部分的,就在这记录下,我学习到的东西吧!
双亲委派模型,即类优先让其父类加载,一般是以组合关系来复用父类加载器。(我就不上图了,网上一大把)。Java有三种类加载器:启动类加载器,扩展类加载器,应用程序类加载器,自定义的类加载器需要继承应用程序类加载器。
值得一提的是,虚拟机识别类,是根据其加载器类本身识别的。同一个类,有不同类加载器加载后,他们是不相等的。
双亲委派模型例子:Tomcat,common类库(其加载器继承应用程序类加载器),tomcat和所有应用程序公用;server类库,只能被tomcat使用;shared类库只能被所有应用程序使用,禁止tomcat使用;WEB-INF类库被特定的应用程序使用。
双亲委派模型的破坏:OSGI,具有热插拔特性,并非按照双亲委派模型。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章