Java类文件结构

Wesley13
• 阅读 467

代码编译的结果从本地机器码转变为字节码(Byte Code),是存储格式发展的一小步,却是编程语言发展的一大步。

存储格式发展:

  今天的计算机仍然只能识别0和1,但将我们编写的程序编译成 二进制本地机器码(Native Code)已不再是唯一的选择,越来越多的程序语言选择了与 操作系统和机器指令集无关的、 平台中立的格式作为程序编译后的存储格式。

   各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节码(ByteCode) 是构成平台无关性的基石,而且语言无关性正越来越被开发者所重视。

  Java虚拟机不和包括Java在内的任何语言绑定,它 只与“Class文件”这种特定的二进制文件格式所关联,Class文件中包含 了 Java虚拟机指令集和符号表以及若干其他辅助信息

Class类文件结构:

结构:

  任何一个Class文件都对应着唯一一个类或接口的定义信息,但反过来说,类或接口并不一定都得定义在文件里(譬如类或接口也可以通过类加载器直接生成)。文中只是通俗地将任意一个有效的类或接口所应当满足的格式称为“Class文件格式”,实际上它并不一定以磁盘文件的形式存在。

  Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件之中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎 全部是程序运行的必要数据,没有空隙存在。当遇到需要占用8位字节以上空间的数据项 时,则会按照高位在前[1]的方式分割成若干个8位字节进行存储。

  Class文件格式采用一种类似于C语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型 :无符号数和表

    无符号数 : 属于基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个 字节和8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8 编码构成字符串值。

     : 是由多个无符号数或者其他表作为数据项构成的复合数据类型,所有表都习惯性地 以“_info”结尾。

组成:

  ①魔数(Magic Number): 每个Class文件的头4个字节称为魔数,它的唯一作用是确定这个文件 是否为一个能被虚拟机接受的Class文件。

  ②版本号 : 第5和第6个字节是次版本号(Minor Version),第7和第8个字节是主版本号(Major Version)。

  ③常量池 : 紧接着主次版本号之后的是常量池入口,常量池可以理解为Class文件之中的资源仓库, 它是Class文件结构中与其他项目关联最多的数据类型,也是占用Class文件空间最大的数据项目之一,同时它还是在Class文件中第一个出现的表类型数据项目

    常量池中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)。

    字面量 : 比较接近于Java语言层面的常量概念,如文本字符串、声明为final的常量值等。

    符号引用 : 则属于编译原理方面的概念,包括了下面三类常量:

      1.类和接口的全限定名(Fully Qualified Name)

      2.字段的名称和描述符(Descriptor)

      3.方法的名称和描述符

  ④访问标志 : 在常量池结束之后,紧接着的两个字节代表访问标志(access_flags),这个标志用于识 别一些类或者接口层次的访问信息,包括:这个Class是类还是接口;是否定义为public类 型;是否定义为abstract类型;如果是类的话,是否被声明为final等。

  ⑤类索引、父类索引和接口索引集合 : 都按顺序排列在访问标志之后.

    类索引(this_class)和父类索引(super_class)都是一个u2类型的数据,接口索引集合(interfaces)是一组u2类型的数据的集合.

    类索引 : 用于确定这个类的全限定名

    父类索引 : 用于确定这个类的父类的全限定名。由于Java语言不允许多重继承,所以父类索引只有一个,除了java.lang.Object之外,所有的Java 类都有父类,因此除了java.lang.Object外,所有Java类的父类索引都不为0。

    接口索引集合 : 就用来描述这个类实现了哪些接口,这些被实现的接口将按implements语句

  ⑥字段表集合 : 用于描述接口或者类中声明的变量。

    字段(field)包括类级变量以及实例级变量,但不包括在方法内部声明的局部变量。我们可以想一想在Java中描述一个字 段可以包含什么信息?可以包括的信息有:字段的作用域(public、private、protected修饰 符)、是实例变量还是类变量(static修饰符)、可变性(final)、并发可见性(volatile修饰 符,是否强制从主内存读写)、可否被序列化(transient修饰符)、字段数据类型(基本类 型、对象、数组)、字段名称。

    字段表集合中不会列出从超类或者父接口中继承而来的字段,但有可能列出原本Java代 码之中不存在的字段,譬如在内部类中为了保持对外部类的访问性,会自动添加指向外部类 实例的字段。另外,在Java语言中字段是无法重载的,两个字段的数据类型、修饰符不管是 否相同,都必须使用不一样的名称,但是对于字节码来讲,如果两个字段的描述符不一致, 那字段重名就是合法的。

   ⑦方法表集合 : 用于对方法的描述,与对字段的描述几乎采用了完全一致的方式.

     访问标志(access_flags)、名称索引(name_index)、描述符索引(descriptor_index)、

     属性表集合(attributes): 方法里的Java代码,经过编译器编译成字节 码指令后,存放在方法属性表集合中一个名为“Code”的属性里面

   ⑧属性表集合 : 在Class文件、字段表、方 法表都可以携带自己的属性表集合,以用于描述某些场景专有的信息。

字节码指令 :

  Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数,Operands)而构成。

  字节码指令集是一种具有鲜明特点、优劣势都很突出的指令集架构,由于限制了Java虚 拟机操作码的长度为一个字节(即0~255),这意味着指令集的操作码总数不可能超过256 条;又由于Class文件格式放弃了编译后代码的操作数长度对齐,这就意味着虚拟机处理那些超过一个字节数据的时候,不得不在运行时从字节中重建出具体数据的结构,如果要将一个 16位长度的无符号整数使用两个无符号字节存储起来(将它们命名为byte1和byte2).

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java虚拟机
  代码编译的结果从本地机器码转换为字节码,是存储格式发展的一小步,却是编程语言发展的一大步。计算机只认识0和1,所以我们的程序需要经过编译器翻译成由0和1组成的二进制格式才能由计算机执行。经过技术的发展,将编写的程序编译成二进制本地机器码已经不是唯一的选择,越来越多的程序语言选择了与操作系统和机器指令无关、平台中立的格式作为程序编译后的存储格式。   
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这