Java的无关性

由于计算机领域中有很多操作系统和硬件平台同时在竞争,所以,很多编程语言的程序设计会与其运行的平台和操作系统产生耦合,这样就大大增加了程序员的工作,为了适应不同的平台,需要修改很多代码。这样,具有无关性特征的Java语言就开始受欢迎了。

平台的无关性:由于有可以运行在不同硬件平台和操作系统上的Java虚拟机,而这些虚拟机都可以载入执行与平台无关的字节码,从而实现了一次编译,到处运行。所有虚拟机都支持一种程序存储格式——字节码,是构成平台无关性的基石

语言的无关性:不同平台上的Java虚拟机可以运行Java以外的语言。语言无关性的基础是虚拟机和字节码存储格式。

为什么Java虚拟机可以运行其他语言的代码呢?

Java代码的运行过程是这样的:首先通过javac编译器将程序编译程类文件,然后通过虚拟机运行类文件即可。那么,这样就将虚拟机与Java语言很好地解耦了,只要能将任何语言编译成符合虚拟机要求的字节码类文件,那样就都能放到Java虚拟机上运行。为此需要做的,就是根据Java虚拟机规范编写相应语言的编译器即可。

Class类文件的结构

class文件时一组以8个子节为基础单位的二进制流,各个数据项目紧凑排列,没有分隔符,空间利用率高。文件中采用一种类似C语言结构体的结构存储数据,只有两类数据类型:无符号数

  • 无符号数
    属于基本的数据类型,里面利用u1、u2、u4、u8来分别标识1个子节、2个子节、4个子节8个子节的无符号数,可以用来描述数字、索引引用、字符串等。


  • 表是由无符号数或者其他表组成的复合数据类型。Class文件本质也是一张表。

class文件的组织结构

  1. 魔数
  2. 本文件的版本信息
  3. 常量池
  4. 访问标志
  5. 类索引
  6. 父类索引
  7. 接口索引集合
  8. 字段表集合
  9. 方法表集合
    10.属性表

1魔数

Class文件的头四个子节被称为魔数,用来标识这个是不是Java虚拟机要的class文件。

这四个子节为:0xCAFEBABE

2版本信息

紧接着魔数的4个子节就是文件的版本号,标识其所使用的JDK版本。第5和第6个字节是次版本号(Minor Version),第7和第8个字节是主版本号(Major Version)。

版本只可以向下兼容。

3常量池

常量池是什么

常量池用于存放class文件的资源,其中包括:

  • 字面量:文本字符串和被声明为final的常量。
  • 复合引用:就是程序中定义的各种名称和定义类型包括:
    • 被模块导出或者开放的包
    • 类和接口的全限定名
    • 字段的名称和描述符
    • 方法的名称和描述符
    • 方法句柄和方法类型
    • 动态调用点和动态常量

常量池的特点

  • 常量池是与其他项目关联最多的数据
  • 使用空间最大的项目之一
  • 第一个出现表类型的数据项目
  • 其中的数据数量不固定,入口需要放置一个u2类型的数据标识常量池的容量
  • 每个常量由一张二维的表组成,除了记录常量的值,还包括其相关信息

常量类型

每一项常量都是一个表,现在一共有17中类型的常量,所以就有17种不同结构的表。

这12种表都有一个共同的特点,第一个位是u1类型的标志位,标识这个常量属于什么类型。

为什么Java中定义类和变量名的长度必须小于64K?

因为class文件中标识类和变量名等名称都是属于符号引用,都是通过常量池中的一个CONSTANT_Utf8_info类型的常量来描述的,而这个类型的常量通过2个子节来存储字符串的长度,最大值是65535,所以这些名字的最大长度是64k。

4访问标志

常量池结束后的两个子节,用于标识一类或接口层次的访问信息。

两个子节十六位,目前只使用了八位,没使用的一律为零。

访问信息包括:

  • 这个Class是类还是接口;
  • 是否定义为public类型;
  • 是否定义为abstract类型;
  • 是类的话,是否为final。

5类索引、父类索引、接口索引集合

用于表示当前类的名字、父类的名字和接口们的名字。这三项数据类用于确定该类型的继承关系。

类索引和父类索引都是两个字节,而接口索引集合就是一组两个字节的数据集合。

类索引是如何找到类的详细信息的呢?
类索引和父类索引用两个u2类型的索引值表示,它们各自能够指向一个类型为CONSTANT_Class_info的类描述符常量,然后通过这个常量中的索引值,可以找到定义在CONSTANT_Utf8_info类型的常量中的全限定名字符串。

接口索引是如何找到其实现接口的详细信息的?
接口索引集合入口第一项就是一个u2类型的数据,作为一个接口计数器,数值代表实现接口数量。如果该类型没有实现任何接口,则计数器的值为0。通过遍历计数器的值,产生一个偏移量,就可以在之后的索引表中查询相应的一个接口索引值,然后通过这个索引值,在常量表中查询对于的接口信息。

6字段表集合

字段表用于描述接口或者类中声明的变量。字段表的集合用于描述本类涉及到的所有成员变量,包括实例变量和类变量,到那时不包括方法中的局部变量。

字段表结构

  1. access_flags:表示访问标志,类似与类的访问标志。其中每个位的含义如下表表示
  2. name_index和descriptor_index:是对常量池的引用,分别表示字段的简单名称以及字段和方法的描述符号。
  3. atrributes_count:表示表集合的长度。
  4. attributes:表属性的集合,用于存储额外的信息。

什么是简单名称和全限定名

简单名称就是没有类型和参数修饰的方法或者字段名称。

全限定名称就是包含类的路径包含信息,例如“org/fenixsoft/clazz/TestClass”。

什么是描述符

成员变量和方法都有自己的描述符。
对于字段而言,描述符是字段的数据类型信息;
对于方法而言,描述符是字段的数据类型、参数列表、返回值信息。

字段表集合的要点

  1. 不会列出从父类或者父接口继承而来的字段。
  2. 可能出先原本代码中不存在的字段。例如编译器为添加指向外部类实例的字段,以满足对内部类访问外部类。
  3. Java程序中不能存在两个相同名字的字段名,但是对于class文件的格式来说,只要两个字段的描述符有区别,字段名相同也是合法的。

7方法表的集合

用于存储类中的方法。
所有的方法以二维表的形式存储,每张表表示一个方法。

对方法的描述和对字段的描述如出一辙。

方法表集合的要点

  1. 如果没有重写父类的的方法,那么本类集合中就不会出现来自父类的方法信息。
  2. 需要重载一个方法时,除了需要与原方法具有相同的简单名称之外,还需要有一个不同的特征签名。特征签名是指这个方法的各个参数在常量池中的字段符号引用的集合。因为返回值不在特征签名之中,所以,Java语言不能仅仅依靠返回值来对一个方法进行重载。而在class文件格式中就是可以的。

8 属性表的集合

用于描述程序运行过程中的相关属性。内容过多且繁杂,这里不做叙述。

深入理解Java虚拟机(七)——类文件结构的更多相关文章

  1. 深入理解Java虚拟机(类文件结构)

    深入理解Java虚拟机(类文件结构) 欢迎关注微信公众号:BaronTalk,获取更多精彩好文! 之前在阅读 ASM 文档时,对于已编译类的结构.方法描述符.访问标志.ACC_PUBLIC.ACC_P ...

  2. 深入理解Java虚拟机(类文件结构+类加载机制+字节码执行引擎)

    目录 1.类文件结构 1.1 Class类文件结构 1.2 魔数与Class文件的版本 1.3 常量池 1.4 访问标志 1.5 类索引.父索引与接口索引集合 1.6 字段表集合 1.7 方法集合 1 ...

  3. 《深入理解Java虚拟机》类文件结构

    上节学习回顾 在上一节当中,主要以自己的工作环境简单地介绍了一下自身的一些调优或者说是故障处理经验.所谓百变不离其宗,这个宗就是我们解决问题的思路了. 本节学习重点 在前面几章,我们宏观地了解了虚拟机 ...

  4. Java虚拟机,类文件结构深度解析

    Java类文件结构 Java虚拟机不和包括Java在内的任何语言绑定,只与 "Class文件" 这种特定的二进制文件所关联, Class文件中包含了Java虚拟机指令集合符号表以及 ...

  5. Java虚拟机——Class类文件结构

    Class文件格式采用一种类似C语言结构体的结构来存储数据,这种数据结构只有两种数据类型:无符号数和表.      无符号数属于基本的数据类型,数据项的不同长度分别用u1, u2, u4, u8表示, ...

  6. Java虚拟机 - Class类文件结构

    [深入Java虚拟机]之二:Class类文件结构 平台无关性 Java是与平台无关的语言,这得益于Java源代码编译后生成的存储字节码的文件,即Class文件,以及Java虚拟机的实现.不仅使用Jav ...

  7. 【深入理解Java虚拟机】类的初始化过程

    类的初始化过程 类的加载过程.png 加载 将 Class 文件以二进制的形式加载到内存中 验证 校验 Class 文件是否安全,是否被正确的修改等 准备 为类变量申请内存,设置默认值,(初始化变量的 ...

  8. 《深入理解 Java 虚拟机》读书笔记:类文件结构

    正文 一.无关性的基石 1.两种无关性 平台无关性: Java 程序的运行不受计算机平台的限制,"一次编写,到处运行". 语言无关性: Java 虚拟机只与 Class 文件关联, ...

  9. 《深入理解java虚拟机》:类的初始化

    深入理解java虚拟机>:类的初始化 类从被载入到虚拟机内存中開始.到卸载出内存为止,它的整个生命周期包含:载入.验证.准备.解析.初始化.使用和卸载七个阶段.当中验证.准备.解析3个部分统称为 ...

随机推荐

  1. UNP第11章——名字与地址转换

    1.域名系统 程序中只使用主机名和服务名的好处是,如果IP或端口变化,只需要改变映射关系,不需要重新编译程序. 1.1 资源记录 DNS的条目为资源记录,有用的项如下: A IPv4地址 AAAA I ...

  2. xenserver使用ceph的rbd的方法

    首先安装的xenserver6.5的环境,看到有地方有提到这个上面可以安装rbd的支持,网上有一种方式是libvirt+kvm方式,因为ceph对libviet是原生支持的,但是xenserver底层 ...

  3. 使用iptables做端口转发

    通过iptables可以做转发 #!/bin/sh IPT="/sbin/iptables" /bin/echo "1" > /proc/sys/net/ ...

  4. Golang中make的使用

    内建函数 make 用来为 slice,map 或 chan 类型分配内存和初始化一个对象(注意:只能用在这三种类型上),跟 new 类似,第一个参数也是一个类型而不是一个值,跟 new 不同的是,m ...

  5. kettle——转换案例

    把stu1的数据按id同步到stu2,stu2有相同id则更新数据 (1)在mysql中创建两张表 mysql> create database kettle; mysql> use ke ...

  6. 08 . Vue脚手架安装,使用,自定义配置和Element-UI导入使用

    Vue脚手架 Vue脚手架可以快速生成Vue项目基础的架构. 安装3.x版本的Vue脚手架 /* npm install -g @vue/cli@3.3 */ 基于3.3版本的脚手架命令创建Vue项目 ...

  7. 讲武德,你们要的高性能日志工具 Log4j2,来了

    Log4j 介绍过了,SLF4J 介绍过了,Logback 也介绍过了,你以为日志系列的文章就到此终结了? 不不不,我告诉你,还有一个 Log4j 2,顾名思义,它就是 Log4j 的升级版,就好像手 ...

  8. vue中插值表达式中时间转换yyyy-MM-dd HH:mm:ss

    vue插值表达式中将时间转换两种方式:一.定义方法 <div id="app">当前实时时间:{{dateFormat(date)}}</div> //时间 ...

  9. pandas 对时间索引进行分割

    截取最近1个月时间,截取最近一段时间,进行统计分析 df.loc["2016-01-05":"2016-02-05",:].tail() 在index为有序数据 ...

  10. 使用Camtasia来消除视频中的声音

    大多数情况下,我们在录制电脑屏幕的时候都会把音频输出也一起录制下来,但也会有时候要后期进行重新配音,需要把事先一同录制的音频消除掉,今天小编来给大家说一说如何消除这种的视频声音. 首先打开Camtas ...