以下内容主要还是参考《Inside JVM》

什么是java类文件

Java类文件是一个精确定义为Java程序二进制文件格式。每个Java类文件是一个Java类或接口的完整描述。没有办法把多个类或接口到单个类文件。精确定义的类文件格式可以确保任何Java类文件可以加载和正确解释任何Java虚拟机,无论什么系统产生的类文件或系统主机的虚拟机。

虽然类文件与Java语言架构,它不是Java语言密不可分。你可以用其他语言编写程序并编译类文件,或者你可以编译Java程序不同的二进制文件格式。然而,大多数Java程序员会使用类文件作为主要工具提供Java虚拟机的程序。

java类文件是一个8位字节的二进制流。数据顺序项存储在没有填充的类文件的相邻的项目之间。没有填充有助于保持紧凑的类文件,超过一个字节的数据是分成几个连续的字节,出现在高位字节顺序中。
就像java类可以包含不同数字的字段,方法,方法参数,局部变量等,java类文件也可以许多大小不同的项目或者数量从一个类文件到另一个地方。在类文件中,类文件的大小或者长度变长项先于实际的数据项,这允许类文件流解析从头到尾,先是读项目的大小然后再读数据。

幻数

每个java类文件的前四个字节都是幻数,以0xCAFEBABE开头。幻数使非java类文件更容易识别。如果一个文件不是以0xCAFEBABE开头,那它绝不是一个java类文件。设计任意没有在广泛使用的任意数字作为一个幻数。当“java”被称为“Oak”时,java类文件的幻数可以选择过去式。帕特里克•诺顿表示 最初的Java团队的关键成员,之前曾说过关于这门语言幻数选择Java名称时。我们正在寻找一些有趣,独特,容易记住。这只是一个巧合0 xcafebabe开头,暗指可爱的咖啡师在皮特的咖啡,预示了Java名称。”

主次版本号

第二个类文件的四个直接包含主次版本号。 随着java技术的发展,新功能偶尔会被添加到java类文件的格式中。每次类文件格式的改变,版本号也会随之改变。对java虚拟机而言,版本号的标示的格式需要遵循一个特定的类文件。Java虚拟机通常能够负载类文件与给定的主版本号和一系列的次要版本号。Java虚拟机必须拒绝类超出它们的有效范围的文件版本号。

常量池数和常量池

类文件中的幻数和版本号都是常量池。常量池包含常量定的类或者接口文件。如这些常量:字符串,final类型的变量,类名,方法名都存储在常量池中。常量池被组织成一个条目列表。在一个计数条目列表中,常量池数优先于实际的列表,常量池。
在常量池中许多元素引用其它元素,和许多类文件中的常量池引用常量池中的元素。整个类文件,常量池条里的元素被整数索引,它们的位置在常量池列表中。列表中的第一个元素的索引,第二个索引,等等。尽管没有在常量池列表中的元素但是它的索引为0,包含在常量池数的常量池数为0 的元素中。例如,如果一个常量池列表包含14个元素(1到14的索引),那么下一个常量池数为15。
每个常量池条目从一个字节标记开始,表明该类型的常量在那个列表中标记这个起始位置。一旦一个java迅即抓住并解析这个标记后,它就知道会发生什么。

上面的表中,是展示的为每个标签对应的表。表的名称是由附加“_info”标签的名字。例如表CONSTANT_Class标签对应的表名称是CONSTANT_Class_info。CONSTANT_Utf8_info表存储压缩的Unicode字符串形式。
在java程序动态链中 常量池扮演着重要的角色。除了字面常量,常量池也包含下面的类型的符号引用。

  • 类和接口的全限定名
  • 字段的名称和描述符
  • 方法名称和描述符
    一个字段是一个类或者接口的实例或者类变量。一个字段描述是一个字符,表示字段类型。方法描述是一个字符,表示该方法返回的类型的参数。常量池是完全限定的名称和使用方法和字段描述符在运行时链接代码在这个类或接口与其他类和接口的代码和数据。类文件不包含信息的最终的内存布局组件,因此类、字段和方法不能直接引用类的字节码文件。Java虚拟机解决任何引用的项目的实际地址在运行时常量池中的象征性参考。例如,字节码指令,调用一个方法给常量池指数的符号引用调用的方法。

    访问标志

    前两个字节在常量池后,访问标志,揭示几项信息关于类文件中定义的类或者接口。首先,访问标志标志是否是一个类或者接口。访问标志也表明修饰符所使用的类或者接口的声明。也可以是抽象或者公共的类和接口。类可以是final类型的,尽管final类型的类不能是抽象的。接口不能是final来修饰。

this_class

接下来的两个字节是this_class项,一个在常量池的索引。常量池的入口位置this_class必须是是表CONSTANT_Class_info,它有两部分:一个标签,一个名字索引。这个标签值是CONSTANT_Class。常量池项入口位置的名字索引将是包含类或者接口的完全限定名的表CONSTANT_Utf8_info。
this_class项提供类一个如何使用常量池。this_class项本身就是一个在常量池中的索引。当java虚拟机查找this_class常量池入口的位置时,它将发现通过标签标示本身的条目CONSTANT_Class_info。java虚拟机知道CONSTANT_Class_info条目索引到常量池中,称为名字索引,在它们的标签后面。所以虚拟机查找name_index常量池入口的位置,应该在哪里找到CONSTANT_Utf8_info条目包含类或接口的完全限定名称

super_class

在类文件在this_class 是super_class的项目,另一个两字节的索引到常量池中。常量池入口位置super_class将CONSTANT_Class_info条目指该类超类的完全限定名称。在java程序中所有对象的基类都是java.lang.Object class,super_class常量池索引对每个类有效除了Object。对于Object类而言,它没有super_class。接口的常量池入口位置的super_class是java.lang.Object。

接口数量和接口

组件super_class始于interfaces_count,超接口的数量计数直接在实现的类或者接口中定义该文件。立即计数接口是一个数组,其中包含一个索引到常量池中为每个超接口直接由这个类或者接口实现。每个超接口由常量池中的一个CONSTANT_Class_info项表示,指的是接口的完全限定名称。唯一的直接超接口,那些出现在类的实现或者接口的扩展,出现在这个数组中。数组中的超接口出现在它们出现的顺序(从左到右)实现或扩展。

字段数和字段

类文件中的接口组件是描述声明这个类或者接口的字段。这个组件是从fields_count开始,一个数量计数的字段,包括类和实例变量。数是表variable-length field_info的列表,对应着每个字段。唯一的字段出现在字段列表中是那些被定义的类或接口中定义的文件。没有字段从超类继承或它的超接口出现在字段列表。

每个 field_info表显示一个字段信息。表中包含字段名称,描述符和修饰符。如果字段声明为final类型,field_info表也揭示该字段的常量值。它的一些信息包含在field_info表中,常量池中包含的位置被称为表。

方法数和方法

通过类或者接口声明的方法描述在类文件中的字段。这个组件从methods_count开始,类或者接口中的双字节方法数量。数只包括那些明确定义的类或接口的方法。

java class file的更多相关文章

  1. java.nio.file.Path

    public interface Path extends Comparable<Path>, Iterable<Path>, Watchable 1. A Path repr ...

  2. Java篇-File类之常用操作

    /** * */ package com.io.file; import java.io.File; import java.io.IOException; /** * <pre> * & ...

  3. Java篇-File类之创建删除

    /** * */ package com.io.file; import java.io.File; import java.io.IOException; import org.junit.Test ...

  4. IO:File类(java.io.File)

    public class File extends Object implements Serializable, Comparable<File> 构造方法: public File(S ...

  5. Java class file format specfication

    Java class file format spec Link: https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html Her ...

  6. java.io.file

    package cn.edu.tongji.cims.wade.system;     import java.io.*;     public class FileOperate {     pub ...

  7. ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn't supported yet

    严重: Context initialization failedorg.springframework.beans.factory.BeanDefinitionStoreException: Fai ...

  8. java获取指定路径下的指定文件/java.io.File.listFiles(FilenameFilter filter)

    java.io.File.listFiles(FilenameFilter filter) 返回抽象路径名数组,表示在目录中此抽象路径名表示,满足指定过滤器的文件和目录. 声明 以下是java.io. ...

  9. 【java IO File】统计项目代码总共多少行

    统计项目代码总共有多少行 思想: 1.首先将不需要迭代的文件夹,保存在集合中,不满足的就是需要迭代的文件夹 2.将需要进行统计行数的代码文件保存在集合中,满足的就是需要计算文件行数的文件 3.迭代方法 ...

  10. 关于Java中File的renameTo函数

    先看Java编程实战经典中的一道习题: 编写程序,程序运行时输入目录名称,并把该目录下的所有文件名后缀修改成.txt. 按照题意,我在d盘新建了文件夹test,并在该文件夹下新建了一个文件file.d ...

随机推荐

  1. Kali-linux无线网络嗅探工具Kismet

    如果要进行无线网络渗透测试,则必须先扫描所有有效的无线接入点.刚好在Kali Linux中,提供了一款嗅探无线网络工具Kismet.使用该工具可以测量周围的无线信号,并查看所有可用的无线接入点.本节将 ...

  2. .net根据经纬度获取地址(百度api)

    private string GetAddress(string lng, string lat) { try { string url = @"http://api.map.baidu.c ...

  3. VSCode调试C++

    在ubuntu下调试C++ 本人觉得VSCode比较好用. 步骤如下: 1. 编写.cpp,.h文件 自行完成自己的程序. 2. 编写CMakeLists.txt.下面是一个比较好用的模板. 根目录为 ...

  4. 编程中关于对时区的理解(语言PHP)

    时间戳 首先来说说time()返回的时间戳,时间戳则是自从 Unix 纪元(格林威治时间 1970 年 1 月 1 日 00:00:00)到当前时间的秒数. 格林威治 由于地球圆的,因此每个时区的时间 ...

  5. Linux Ubuntu出去看看

    转到Ubuntu开发之后,发现不能像之前在Windows下一样直接使用GUI客户端出去看看.于是开始找梯子. 由于我的服务器端已经配置好了,只需要配置本地端即可.整个配置过程分为两步:第一步是安装本地 ...

  6. 【noip 模拟赛curse,light,maze】 题解

    2018.10.16 总结:考的不好 原因: 1.考的时候没状态,读题读不进去 2.考的时候不仔细,该得分没得到 T1:curse 1.咒语 (curse.pas/c/cpp) [题目描述] 亮亮梦到 ...

  7. Swift 开发语法

    文/Tuberose(简书作者)原文链接:http://www.jianshu.com/p/5e2d4c34f18e著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 简介 Swift 语 ...

  8. java点滴之MulticastSocket的使用

    一基本概念 该类恰是上文介绍的DatagramSocket的子类. DatagramSocket仅仅同意数据报发送给指定的目标地址,而MulticastSocket能够将数据报以广播的方式发送到多个c ...

  9. Powerdesigner设置表字段注释与name相同

    Powerdesigner设置当表字段注释为空时与name相同 1.在Database-->edit Current DBMS-->script-->objects-->col ...

  10. Activiti6.0 spring5 工作流引擎 java SSM流程审批 项目框架

    1.模型管理 :web在线流程设计器.预览流程xml.导出xml.部署流程 2.流程管理 :导入导出流程资源文件.查看流程图.根据流程实例反射出流程模型.激活挂起 3.运行中流程:查看流程信息.当前任 ...