字节码是构成Java平台无关性的基石。实现语言无关性的基础是虚拟机和字节码存储格式。
Java语言中的各种变量、关键字和运算符的语义最终是由多条字节码命令组成,因此字节码命令所能提供的语义描述能力肯定会比Java语言本身更强大。
Class类文件的结构
Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件中,中间没有添加任何分隔符,所以整个Class文件中存储的内容基本上程序运行中必要的数据。
当遇到需要占用8位字节以上空间的数据项时,则会按照位字节进行存储。
Class文件的格式:类似于C语言结构体的伪结构来存储,这种伪结构只有两种数据类型:无符号数和表,后面的解析以这两种数据类型为基础。
1)无符号数:属于基本的数据类型,无符号数可以描述数字、索引引用、数量值或者是按照UTF-8编码构成字符串值。
2)表:由多个无符号数或者其他表作为数据项构成的复合数据类型。表用于描述有层次关系的复合结构的数据。整个Class文件本质上就是一张表。
无论是无符号数还是表,当需要描述同一类型但数量不定的多个数据时,经常会使用一个前置的容量计数器加若干个连续的数据项的形式,这时候称这一系列连续的某一类型的数据为某一类型的集合。
Class文件中的数据项无论是顺序还是数量,都是被严格限定的,哪个字节代表什么意思,长度是什么样的,先后顺序如何,都是不允许改变的。
结构详解:
1)magic:魔数,头四个字节,它的作用是用于确定这个文件是否为一个能被虚拟机接受的Class文件。很多文件存储标准中都使用魔数来进行身份识别,如图片格式等。
使用魔数而不是扩展名来进行识别主要是基于安全考虑,因为文件扩展名是可以随意修改的。
Class文件的魔数值为:0xCAFEBABE。
2)Minor Version、Major Version(Class文件的版本号):在魔数之后的4个字节。第5、6个字节是次版本号(Minor Version),第7、8个字节是主版本号(Major Version)。
Java版本号是从45开始的,JDK1.1之后的每个JDK大版本发布主版本号向上加1(JDK 1.0~1.1 使用45.0~45.3的版本号),高版本的JDK能向下兼容以前版本的Class文件,但不能向后兼容。
3)constant-pool常量池:常量池是Class文件结构中与其他项目关联最多的数据类型,也是占用Class文件空间最大的数据项目之一,同时它还是Class文件中第一个出现的表类型数据项目。
由于常量池中的常数的数量是不固定的,所以在常量池的入口处放置一项u2(代表两个字节)类型的数据,代表常量池容量计数值(constant-pool-count)。值得注意的是:这个容量计数是从1而不是从0开始的。原因是为了满足后面某些指向常量值得索引值的数据在特定情况下需要表达“不引用任何一个常量池项目”的意思。
常量池中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)。字面量比较接近于Java语言层面的常量概念,如文本字符串、被声明为final的常量值。而符号引用则属于编译原理方面的概念,包括:a、类和接口的全限定名(Fully Qualified Name);b、字段的名称和描述符(Descriptor);c、方法的名称和描述符。
Java代码在进行Javac编译时,不像C或者C++那样的“连接”这一步骤,而是在虚拟机加载Class文件的时候进行动态加载。所以,在Class文件中不会保存各种方法和字段的最终内存布局信息,因此这些字段和方法的符号引用不经过转换的话就无法让虚拟机使用。当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或者运行时解析并翻译到具体的内存地址中。
常量池中的每一项常量都是一个表,共有11种结构各不相同的表结构数据。这11种表都有一个共同的特点,就是表开始的第一位是一个u1类型的标志位(tag,取值为1~12,缺少标志为2的数据类型),代表这个常量属于哪种常量类型。
如:CONSTANT_Class_info型常量的结构:(u1)tag + (u2)name_index,标志位+索引值,索引值指向常量池中的一个CONSTANT_Utf-8_info类型的常量,此常量代表这个类(或者接口)的全限定名。
CONSTANT_Utf8_info型常量的结构:(u1)tag+(u2)length+(u1)bytes,标志位+字符串长度的字节+数量为length的bytes值。
Class文件中方法、字段等都需要引用CONSTANT_Utf8_info型常量来描述名称,所以CONSTANT_Utf8_info型常量的最大长度也就是Java中方法和字段名的最大长度,最大值是65535.所以Java程序中如果定义了超过64KB英文字符的变量或方法名,将会无法编译。
javap可以用来分析Class文件字节码,用javap -verbose参数输出Class文件的字节码内容。
4)access_flags(访问标志):在常量池结束后,紧接着的2个字节代表访问标志(access_flags),这个标志用来识别一些类或接口层次的访问信息,包括:这个Class是类还是接口,是否定义为public类型,是否定义为abstract类型,如果是类。是否被声明为final等等。
access_flags中一共有32个标志位可以使用,当前只定义了其中的8个,其他的标志位要求一律为0.
5)this_class、super_class、interfaces(类索引、父类索引和接口索引集合):this_class和super_class都是一个u2类型的数据,而接口索引集合是一组u2类型的数据的集合。Class文件中由这三项数据来确定这个类的继承关系。
类索引用于确定这个类的全限定名,父索引用于确定这个类的父类的全限定名。由于java语言不允许多重继承,所以父索引只有一个,且不为空。接口索引集合描述了这些类实现了哪些接口,它们按照继承的顺序依次从左到右排列在接口集合中。
类索引、父类索引和接口索引集合都按照顺序排列在访问标志之后。类索引和父类索引引用两个u2类型的索引值表示,他们各自指向一个类型为CONSTANT_Class_info的类描述符常量,通过其内的索引值找到定义在CONSTANT_Utf8_info类型的常量中的全限定名字符串。而对于接口索引集合,入口的第一项是u2类型的接口计数器(interfaces_count)表示索引表的容量。
6)filed_info(字段表集合):用于描述接口或类中声明的变量。字段(filed)包括了类级变量或实例化变量,但不包括在方法内部声明的变量。
字段中包括的信息:字段的作用域(public、private、protected修饰符)、是类级变量还是实例级变量(static修饰符)、可变性(final)、并发可见性(volatile修饰符)、可否序列化(reansient修饰符)、字段数据类型(基本类型、对象、数组)、字段名称等。在这些信息中,各个修饰符都是布尔值,要么有,要么没有。而字段叫什么名字、字段被定义成什么数据类型,这些都是无法固定的,只能引用常量池中的常量来描述。
字段表结构:
字段访问标志:
跟随access_flags标志的是两项索引值,name_index和descriptor_index。它们都是对常量池的引用,分别代表着字段的简单名称及字段和方法的描述符。
描述符标识字符含义:
对于数组类型,每一个维度将使用一个前置的“【”来描述。如“【I”:一个整型数组。
用描述符来描述方法时,按照先参数列表,后返回值的顺序描述,参数列表按照严格顺序放在一组小括号之内。如方法void inc()的描述符为“()V”。
字段表集合中不会列出从超类或者父接口中继承而来的字段,但有可能列出原本java代码之中不存在的字段,如在内部类中为了保持对外部类de访问性,会自动添加指向外部类实例的字段。
7)methods(方法表集合):
方法访问标志:
8)attribute_info(属性表集合):在Class文件、字段表、方法表中都可以携带自己的属性表集合,以用于描述某些场景专有的信息。
虚拟机规范预定义的属性:
- 深入理解JVM(六)类文件结构
6.1 关于类文件 1.class文件的一次编译,到处运行的跨平台性: 2.JVM不止有跨平台性,还有跨语言性,不管是JRuby还是Groovy写出来的程序,只要编译出符合JVM规范的class文件就 ...
- JVM(4) 类文件结构
一.实现“平台无关性” 字节码(ByteCode)存储格式和虚拟机是实现语言无关性的基础.Java虚拟机不和包括Java在内的任何语言绑定,它只与“Clas”文件这种特定的二进制文件格式所关联,Cla ...
- JVM学习笔记(三):类文件结构
代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步. 实现语言无关性的基础是虚拟机和字节码存储格式.Java虚拟机不和包括Java在内的任何语言绑定,只与&quo ...
- jvm 类文件结构学习
本文以代码示例来学习 java 类文件的结构,其中对类文件结构的学习均来自周志明先生所著的 <深入理解 Java 虚拟机>一书,在此表示诚挚的感谢. 代码如下: package com.r ...
- 【搞定Jvm面试】 面试官:谈谈 JVM 类文件结构的认识
类文件结构 一 概述 在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机.Java 语言通过字节码的方式,在一定程度上解决 ...
- 四、JVM — 类文件结构
类文件结构 一 概述 二 Class 文件结构总结 2.1 魔数 2.2 Class 文件版本 2.3 常量池 2.4 访问标志 2.5 当前类索引,父类索引与接口索引集合 2.6 字段表集合 2.7 ...
- jvm(4):类文件结构
typora-root-url: ./ 类文件结构 魔数Magic Number 每个Class文件的头4个字节是魔数.值为0xCAFEBABE 唯一作用:确定这个文件是一个能被虚拟机接受的Class ...
- JVM类文件结构
作为一名Java后台开发的程序员, 深入理解JVM, 重要性不言而喻, 这篇文章主要是记录JVM类文件结构相关知识. 2. 实例 这部分比较抽象, 所以以实例的形式来学习. 这部分作为资料, 以便后面 ...
- JVM学习第三天(JVM的执行子系统)之开篇Class类文件结构
虽然这几天 很忙,但是学习是不能落下的,也不能推迟,因为如果推迟了一次,那么就会有无数次;加油,come on! Java跨平台的基础: 各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节 ...
随机推荐
- web12 使用map型的request、session、application
电影网站:www.aikan66.com 项目网站:www.aikan66.com 游戏网站:www.aikan66.com 图片网站:www.aikan66.com 书籍网站:www.aikan66 ...
- servlet几个常用的方法
servlet继承了HTTPServlet所以可以重写父类的方法,下面一 一介绍方法Dopost DoGet 比较常用不再介绍. 一.Init(),和Init(ServletConfig config ...
- sql索引的填充因子多少最好,填充因子有什么用
和索引重建最相关的是填充因子.当创建一个新索引,或重建一个存在的索引时,你可以指定一个填充因子,它是在索引创建时索引里的数据页被填充的数量.填充因子设置为100意味着每个索引页100%填满,50%意味 ...
- Spring笔记⑥--整合struts2
Spring如何在web应用里面用 需要额外加入的jar包 Spring-web-4.0.0 Spring-webmvc-4.0.0 Spring的配置文件,没什么不同 需要在web.xml下配置 ...
- 第三个spirit(第十四天)
一 .进度(自习室) 本来十号要开始进行第三次冲刺,不过因为团队很多成员要进行协会和组织的换届,而且团队还换了新 人又加了人进来,所以我们今天才是第三次冲刺的第一天.我们进行了新团队的第一次会议.基于 ...
- 《TCP/IP 详解 卷1:协议》第 5 章:Internet 协议
IP 是 TCPIP 协议族中的核心协议.所有 TCP.UDP.ICMP.IGMP 数据都通过 IP 数据包(又称为 packet)来传输.IP 的英文名为 Internet Protocol,是互联 ...
- git的使用(本地及关联远程,上传到远程)
前言:本想这个博客就是用来交作业的,因为作业,学习了git ,现在觉得,既然有这个博客了,就好好用一下吧,也给自己养成个好习惯,就也来记录一下吧,关于git的本地仓库上传,本地与远程的关联,从本地上传 ...
- 项目冲刺Beta第二篇博客
Beta版本冲刺计划安排 1.当天站立式会议照片: 2.工作分工: 团队成员 分工 张洪滨060 排行榜界面美化 陈敬轩059 注册成功界面美化 黄兴067 登录界面美化 林国梽068 答题界 ...
- maven编译,控制台中文乱码解决方案
如下图,在使用maven运行后,在控制台看到中文展示乱码 出现这个的原因是源码使用UTF-8,但是maven编译的时候使用GBK标准,如下图 为了让maven编译的时候使用UTF-8标准,使用在p ...
- yii2微博第三方登录
原作者:杜文建 原博客:http://www.cnblogs.com/dwj97/p/6530568.html yii2微博第三方登录 微博登录是最常用的第三方账号登录之一.由于其网站用户量大,可 ...