深入理解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个部分统称为 ...
随机推荐
- UI自动化中无头浏览器的应用
因为某次工作中写了个脚本要来回跑,还要在本机上做很多其他的事情,所以就上网找了个方法,无头浏览器,这样就不会浏览器来回弹出来,执行用例还会很快. 废话不多说,直接放代码: #coding=utf-8 ...
- bluestore的osd自启动
前言 自启动相关的文章很多,有分析的很详细的文章,这里就不做赘述,本篇讲述的是什么情况下用,怎么用的问题 使用场景 一台机器的系统盘坏了,需要重装系统,相关的一些信息没有了,但是上面的数据盘还是在的, ...
- Python_列表相减(判断长度后长的减短的)
#定义一个方法,可进行列表相减 class V(object): def __init__(self,*value): self.value=value def __sub__(self,other) ...
- html 小米商城导航栏示例
1.小米导航栏示例 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset=&q ...
- Windows上Jenkins插件下载慢解决方法
替换文件内容 Jenkins/updates/default.json 替换 updates.jenkins-ci.org/download 为 mirrors.tuna.tsinghua.edu.c ...
- Hash算法——加密解密说明
MD5 pmd5-md5加密解密 加密类型识别工具 hash-identifier
- MQ消息中间件,面试能问些什么?
MQ消息中间件,面试能问些什么? 为什么使用消息队列?消息队列的优点和缺点? kafka.activemq.rabbitmq.rocketmq都有什么优缺点? 面试官角度分析: (1)你知不知道你们系 ...
- python 中 try...finally... 的优雅实现
1. 关于 try.. finally.. 假如上帝用 python 为每一个来到世界的生物编写程序,那么除去中间过程的种种复杂实现,最不可避免的就是要保证每个实例最后都要挂掉.代码可简写如下: tr ...
- 如何基于App SDK快速地开发一个IoT App?
一.背景及大纲介绍 在如今物联网DCM(Device.Connect.Manage)的大框架下,有一个应用层来分析和处理数据,是必备技能.但是,对于一个公司来说,因为研发能力或者研发时间的原因,可能很 ...
- 《HelloGitHub》第 56 期
兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. 这是一个面向编程新手.热爱编程.对开源社区感兴趣 人群的月刊,月刊的内容包括:各种编 ...