深入理解Java虚拟机(七)——类文件结构
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文件的组织结构
- 魔数
- 本文件的版本信息
- 常量池
- 访问标志
- 类索引
- 父类索引
- 接口索引集合
- 字段表集合
- 方法表集合
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字段表集合
字段表用于描述接口或者类中声明的变量。字段表的集合用于描述本类涉及到的所有成员变量,包括实例变量和类变量,到那时不包括方法中的局部变量。
字段表结构
- access_flags:表示访问标志,类似与类的访问标志。其中每个位的含义如下表表示
- name_index和descriptor_index:是对常量池的引用,分别表示字段的简单名称以及字段和方法的描述符号。
- atrributes_count:表示表集合的长度。
- attributes:表属性的集合,用于存储额外的信息。
什么是简单名称和全限定名
简单名称就是没有类型和参数修饰的方法或者字段名称。
全限定名称就是包含类的路径包含信息,例如“org/fenixsoft/clazz/TestClass”。
什么是描述符
成员变量和方法都有自己的描述符。
对于字段而言,描述符是字段的数据类型信息;
对于方法而言,描述符是字段的数据类型、参数列表、返回值信息。
字段表集合的要点
- 不会列出从父类或者父接口继承而来的字段。
- 可能出先原本代码中不存在的字段。例如编译器为添加指向外部类实例的字段,以满足对内部类访问外部类。
- Java程序中不能存在两个相同名字的字段名,但是对于class文件的格式来说,只要两个字段的描述符有区别,字段名相同也是合法的。
7方法表的集合
用于存储类中的方法。
所有的方法以二维表的形式存储,每张表表示一个方法。
对方法的描述和对字段的描述如出一辙。
方法表集合的要点
- 如果没有重写父类的的方法,那么本类集合中就不会出现来自父类的方法信息。
- 需要重载一个方法时,除了需要与原方法具有相同的简单名称之外,还需要有一个不同的特征签名。特征签名是指这个方法的各个参数在常量池中的字段符号引用的集合。因为返回值不在特征签名之中,所以,Java语言不能仅仅依靠返回值来对一个方法进行重载。而在class文件格式中就是可以的。
8 属性表的集合
用于描述程序运行过程中的相关属性。内容过多且繁杂,这里不做叙述。
深入理解Java虚拟机(七)——类文件结构的更多相关文章
- 深入理解Java虚拟机(类文件结构)
深入理解Java虚拟机(类文件结构) 欢迎关注微信公众号:BaronTalk,获取更多精彩好文! 之前在阅读 ASM 文档时,对于已编译类的结构.方法描述符.访问标志.ACC_PUBLIC.ACC_P ...
- 深入理解Java虚拟机(类文件结构+类加载机制+字节码执行引擎)
目录 1.类文件结构 1.1 Class类文件结构 1.2 魔数与Class文件的版本 1.3 常量池 1.4 访问标志 1.5 类索引.父索引与接口索引集合 1.6 字段表集合 1.7 方法集合 1 ...
- 《深入理解Java虚拟机》类文件结构
上节学习回顾 在上一节当中,主要以自己的工作环境简单地介绍了一下自身的一些调优或者说是故障处理经验.所谓百变不离其宗,这个宗就是我们解决问题的思路了. 本节学习重点 在前面几章,我们宏观地了解了虚拟机 ...
- Java虚拟机,类文件结构深度解析
Java类文件结构 Java虚拟机不和包括Java在内的任何语言绑定,只与 "Class文件" 这种特定的二进制文件所关联, Class文件中包含了Java虚拟机指令集合符号表以及 ...
- Java虚拟机——Class类文件结构
Class文件格式采用一种类似C语言结构体的结构来存储数据,这种数据结构只有两种数据类型:无符号数和表. 无符号数属于基本的数据类型,数据项的不同长度分别用u1, u2, u4, u8表示, ...
- Java虚拟机 - Class类文件结构
[深入Java虚拟机]之二:Class类文件结构 平台无关性 Java是与平台无关的语言,这得益于Java源代码编译后生成的存储字节码的文件,即Class文件,以及Java虚拟机的实现.不仅使用Jav ...
- 【深入理解Java虚拟机】类的初始化过程
类的初始化过程 类的加载过程.png 加载 将 Class 文件以二进制的形式加载到内存中 验证 校验 Class 文件是否安全,是否被正确的修改等 准备 为类变量申请内存,设置默认值,(初始化变量的 ...
- 《深入理解 Java 虚拟机》读书笔记:类文件结构
正文 一.无关性的基石 1.两种无关性 平台无关性: Java 程序的运行不受计算机平台的限制,"一次编写,到处运行". 语言无关性: Java 虚拟机只与 Class 文件关联, ...
- 《深入理解java虚拟机》:类的初始化
深入理解java虚拟机>:类的初始化 类从被载入到虚拟机内存中開始.到卸载出内存为止,它的整个生命周期包含:载入.验证.准备.解析.初始化.使用和卸载七个阶段.当中验证.准备.解析3个部分统称为 ...
随机推荐
- vue 使用中的小技巧 (一)
在vue的使用过程中会遇到各种场景,当普通使用时觉得没什么,但是或许优化一下可以更高效更优美的进行开发.下面有一些我在日常开发的时候用到的小技巧 data 和 Object.freeze 每个Vue实 ...
- 七:Redis的持久化
1.RDB(Redis DataBase) 1.1 定义:在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的snapshot快照,他恢复时是将快照文件直接读到内存里 是什么:Redis会单 ...
- brctl 增加桥接网卡
前言 之前有一篇介绍配置桥接网卡的,这个桥接网卡一般是手动做虚拟化的时候会用到,通过修改网卡的配置文件的方式会改变环境的原有的配置,而很多情况,我只是简单的用一下,并且尽量不要把网络搞断了,万一有问题 ...
- 源码分析:升级版的读写锁 StampedLock
简介 StampedLock 是JDK1.8 开始提供的一种锁, 是对之前介绍的读写锁 ReentrantReadWriteLock 的功能增强.StampedLock 有三种模式:Writing(读 ...
- Elementary OS常见软件(TIM、微信、企业微信)安装(二)
前言 最终没忍住还是把开发环境迁移到了Elementary OS上来,这其中也没少折腾,试过Ubuntu 20.04 LTS和deepin V20可以(),deepin真的很不错可能是我的电脑兼容性不 ...
- 【进阶之路】Redis基础知识两篇就满足(一)
导言 大家好,我是南橘,一名练习时常两年半的java练习生,这是我在博客园的第一篇文章,当然,都是要从别处搬运过来的,不过以后新的文章也会在博客园同步发布,希望大家能多多支持^_^ 这篇文章的出现,首 ...
- PHP弱类型漏洞学习
简介 PHP在使用双等号(==)判断的时候,不会严格检验传入的变量类型,同时在执行过程中可以将变量自由地进行转换类型.由于弱数据类型的特点,在使用双等号和一些函数时,会造成一定的安全隐患 eg: &l ...
- MongoDB动态建表方案(官方原生驱动)
MongoDB动态建表方案(官方原生驱动) 需求前提:表名动态,表结构静态,库固定 1.导入相关依赖 <dependency> <groupId>org.mongodb< ...
- 怎么在苹果笔记本上用Folx重新下载已完成的任务
大家在完成了任务下载后,有时会将下载的文件移动到其他文件夹中,或者是,当下载的文件已经使用完毕时,有些用户会将文件删除.以上的两种情况,都会导致Folx所属任务查看功能失效,也就是说,无法找到任务对应 ...
- 精尽MyBatis源码分析 - SQL执行过程(三)之 ResultSetHandler
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...