类文件结构和类加载机制

类文件结构:

Overview:
  • java虚拟机只和Class 文件这种特定的二进制文件格式所关联,以实现语言无关性。
  • Class文件中包含了java虚拟机指令集和符号表以及若干其他辅助信息,任何一门功能性语言都可以表示为一个能被Java虚拟机所接受的有效的Class文件
  • 字节码命令所能提供的语义描述能力要比java更加强大,java中的各种变量,关键字和运算符号的语义最终都由多条字节码命令组合而成
  • java虚拟机执行字节码引擎是基于栈的体系结构。
  • java字节码放弃了操作数长度对齐,就意味可以省略很多填充和间隔符号。
  • Class文件所具备的平台独立性(不依赖于特定的硬件和操作系统),紧凑,稳定和可扩展的特点,是Java技术体系实现平台无关,语言无关两项特性的重要支柱。
Class文件结构:
  • 任何一个class文件都对应着唯一一个类或者接口的定义信息。
  • class文件是一组以8位字节为基础单位的二进制流
  • 整个class文件本质上就是一张表
    • 表是由多个无符号数或者其他作为数据项构成的复合数据类型。表用于描述有层次关系的复合结构的数据
    • 无符号数属于基本的数据类型,可以用来描述数字,索引引用,数量值或者utf-8编码的字符串
  • 魔数:4字节,表示这个文件是不是一个class文件。
  • 次要版本号和主要版本号。
  • 常量池。存放字面量和符号引用。常量中的每一项都是一个
  • 字面量: 字符串,声明为final的常量等
  • 符号引用:
    • 类和接口的全限定名
    • 字段的名称和描述符
    • 方法的名称和描述符
  • 虚拟机加载class文件时进行动态连接,在class文件中不保存各个方法字段的最终内存布局。 在运行的时解析。
  • Class文件格式:
    Class文件格式
字节码指令简介
  • java虚拟机指令由一个字节长度的操作码和跟随其后的零至多个此操作所需参数构成
  • java虚拟机采用面向操作数栈而不是寄存器的结构,所以大多数指令都不包含操作数,只有一个操作码
  • class文件格式放弃了编译后代码的操作数长度对齐,意味着可以省略很多填充和间隔符号,但对于超过一个字节的数据,却不得不在运行时从字节中重建出具体数据的结构,这种操作导致解释执行字节码时损失了一些性能
  • 大多数对于boolean,byte,short和char类型数据的操作,实际上都是使用相应的int类型作为运算类型

虚拟机类加载机制

overview:
  • 定义:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的java类型。
  • 特点:java语言中,类型的加载,连接和初始化过程都是在程序运行期间完成的,这样为java应用程序提供了高度的灵活性; java可以动态扩展就是依赖于运行期动态加载和动态连接两个特性实现的
  • 加载过程中各个步骤互相交叉的混合进行。

类加载过程:

这里写图片描述

  • 加载过程: 一个类必须与类加载器一起确定唯一性

    1. 通过一个类的全限定名获得定义此类的二进制字节流(字节码)**
    2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
    3. 生成java.lang.Class对象(放在方法区中),作为方法区中这个类的各种数据的访问入口。
  • 验证: 为了保证class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

    1. 文件格式验证,这阶段的验证是基于二进制字节流进行的,只有通过这个阶段,字节流才会进入内存的方法区中进行存储
    2. 元数据验证,主要目的是对类的元数据信息进行语义校验,保证元数据符合java语言规范
    3. 字节码验证,通过数据流和控制流分析,确定程序语义是合法的,如对类的方法进行校验
    4. 符号引用验证,发生在虚拟机将符号引用转化为直接引用的时候;目的是为了确保解析动作能正常执行
  • 准备:正式为类变量(static)分配内存,设置类变量(static)初始值(0值,具体的值在初始化阶段后执行,如果是final,则在此阶段赋值)的阶段。

  • 解析:虚拟机将池中的符号引用替换为直接引用的过程。
    备注:由于class会保存符号引用用于描述方法字段等,而不会储存各个方法,字段的最终内存布局,所以需要进行运行的转换才可以使用。

    符号引用(描述目标):以一组符号来描述所引用的目标,符号是任意形式的字面量。
    直接引用(找到目标):可以直接指向目标的指针,偏移量等。

  • 初始化:到了该阶段,才真正开始执行类中定义的Java程序代码。或者说初始化阶是执行类构造器()方法(由编译器收集类中的静态变量的赋动作和静语句块合并而成)的过程。

    • 对于静态字段,只有直接定义这个字段的类才会被初始化。
    • 当一个类在初始化时,要求其父类全部都已经初始化过了。
    • 一个接口在初始化的时,并不要求其父接都完成了初始化,只有在真正使用到父接口的时候才会初始化。
  • 类加载器(用于实现类的加载动作):

    • 定义:类加载器用于“通过一个类的全限定名来获取描述此类的二进制字节流”的动作。
    • 对于任意一个类,都需要由加载它的类加载器和这个类本身一起确定其在java虚拟机中的唯一性,这适用于equals,isAssignableFrom,isInstance,instanceof方法
    • 每一个类加载器,都拥有一个独立的命名空间
    • 类加载器的双亲委派模型:
      1. 2种类加载器: (1)启动类加载器,是虚拟机的一部分,c++实现 (2)独立于虚拟机外部由java实现的类加载器,都继承自java.lang.ClassLoader
      2. 一个类加载器将请求交给父亲加载器去完成,每一个层次的加载器都是如此。只父亲无法加载时,才由儿子加载。这基于前提,一个类由它自己和加载它的类加载器唯一确定;
      3. 双亲委派模型很好的解决了各个类加载器的基础类的统一问题(越基础的类由越上层的加载器进行加载)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值