字节码是构成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小结--类文件结构的更多相关文章

  1. 深入理解JVM(六)类文件结构

    6.1 关于类文件 1.class文件的一次编译,到处运行的跨平台性: 2.JVM不止有跨平台性,还有跨语言性,不管是JRuby还是Groovy写出来的程序,只要编译出符合JVM规范的class文件就 ...

  2. JVM(4) 类文件结构

    一.实现“平台无关性” 字节码(ByteCode)存储格式和虚拟机是实现语言无关性的基础.Java虚拟机不和包括Java在内的任何语言绑定,它只与“Clas”文件这种特定的二进制文件格式所关联,Cla ...

  3. JVM学习笔记(三):类文件结构

    代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步. 实现语言无关性的基础是虚拟机和字节码存储格式.Java虚拟机不和包括Java在内的任何语言绑定,只与&quo ...

  4. jvm 类文件结构学习

    本文以代码示例来学习 java 类文件的结构,其中对类文件结构的学习均来自周志明先生所著的 <深入理解 Java 虚拟机>一书,在此表示诚挚的感谢. 代码如下: package com.r ...

  5. 【搞定Jvm面试】 面试官:谈谈 JVM 类文件结构的认识

    类文件结构 一 概述 在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机.Java 语言通过字节码的方式,在一定程度上解决 ...

  6. 四、JVM — 类文件结构

    类文件结构 一 概述 二 Class 文件结构总结 2.1 魔数 2.2 Class 文件版本 2.3 常量池 2.4 访问标志 2.5 当前类索引,父类索引与接口索引集合 2.6 字段表集合 2.7 ...

  7. jvm(4):类文件结构

    typora-root-url: ./ 类文件结构 魔数Magic Number 每个Class文件的头4个字节是魔数.值为0xCAFEBABE 唯一作用:确定这个文件是一个能被虚拟机接受的Class ...

  8. JVM类文件结构

    作为一名Java后台开发的程序员, 深入理解JVM, 重要性不言而喻, 这篇文章主要是记录JVM类文件结构相关知识. 2. 实例 这部分比较抽象, 所以以实例的形式来学习. 这部分作为资料, 以便后面 ...

  9. JVM学习第三天(JVM的执行子系统)之开篇Class类文件结构

    虽然这几天 很忙,但是学习是不能落下的,也不能推迟,因为如果推迟了一次,那么就会有无数次;加油,come on! Java跨平台的基础: 各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节 ...

随机推荐

  1. MathExam6317

    自己取一个大气又可爱的标题 小学二年级的还没来得及写,大部分时间还是花在巩固和查阅新旧知识上了,通过看学习视频,查资料,看博客园的博客...下次完善好了交上. 一.预估与实际 PSP2.1 Perso ...

  2. 【CS231N】3、Softmax分类器

    wiki百科:softmax函数的本质就是将一个K维的任意实数向量压缩(映射)成另一个K维的实数向量,其中向量中的每个元素取值都介于(0,1)之间. 一.疑问 二.知识点 1. softmax函数公式 ...

  3. 第五次作业——python效能分析与几个问题(个人作业)

    第五次作业--效能分析与几个问题(个人作业) 前言 阅读了大家对于本课程的目标和规划之后,想必很多同学都跃跃欲试,迫不及待想要提高自身实践能力,那么就从第一个个人项目开始吧,题目要求见下. 阅读 阅读 ...

  4. just_sort

    ★实验任务 给定两个序列 a b,序列 a 原先是一个单调递增的正数序列,但是由于某些 原因,使得序列乱序了,并且一些数丢失了(用 0 表示).经过数据恢复后,找 到了正数序列 b ,且序列 a 中 ...

  5. Beta阶段团队项目开发篇章4

    例会时间 2016.12.11 例会照片 个人工作 上阶段任务验收 删除robot功能较为简单,基本实现,但是一直Question版块任务量过大,考虑到最近要进行编译课设第二次测试,为该任务再分配一段 ...

  6. matlab的应用

    MATLAB在信号与系统中的应用 一: 看到MATLAB在信号与系统中的应用,对这部分我比较熟悉,在此举一个小例子.    impulse(sys)表示求连续系统sys的冲击响应    subplot ...

  7. 第九周(11.11-11.17)----Beta版本发布140字评论

    1.新蜂组: 俄罗斯方块:项目有良好的用户界面,在原版的基础上可以对用户分数进行排序,增加了显示下一个方块的功能.是个很有趣的小游戏. 2.天天向上组: 连连看:完成了基本功能,增加了消除时和鼠标点击 ...

  8. 相见恨晚的 scala - 01 [ 基础 ]

    简洁到不行,多一个分号都是不应该. 学习笔记: centOS 下安装 scala 和安装 jdk 一毛一样 . 1 . 不同于 Java 的变量声明 :( 但是和 js 很像 ) /** * Crea ...

  9. Codeforces 449B_Jzzhu and Cities

    给一个无向图,外加一些特殊的连接原点的无向边.在不改变原点与所有点的最短路的情况下,最多可以删除多少条特殊边? 首先我们把所有的边夹杂在一起.spfa跑出与所有点的最短路. 接下来我们通过一次bfs来 ...

  10. 每日一问(如何在List中加入、设置、获取和删除其中的元素?)

    作为集合接口的一部分,对List接口所做的操作,最常见的就是增删查改了.这里总结下JAVA 中List接口及实现该接口的类实现这些操作的方法. 一.增加新的元素的方法 在Collection接口中定义 ...