将java代码编译后会产生class文件,并且一个clas文件会对应唯一一个java类或者接口。下面对一个通过一个简单的例子来简述一下class文件的结构。

java代码

  1. public class JavaMethodAreaOOM{
  2. String str = "abc";
  3. int i = 1;
  4. static String str1 = "123";
  5.  
  6. public static void main(String[] args) {
  7. int b = 1;
  8. }
  9.  
  10. public void test(){
  11. System.out.println(str1);
  12. }
  13. }

在java代码中我们定义了一些属性和方法。下面是编译生成的字节码文件

字节码文件

我们看到,源代码不长,但是生成的字节码文件内容却很多,下面就针对上面的例子进行分析。

字节码分析

  在字节码文件中只存储了两种类型的数据,一种是无符号数(u1,u2,u4,u8,u1表示一个字节,u2表示两个字节...),一种是表(表其实就是无符号的集合,不过表中的数据之间是有联系的,而且表中还可以存放表,表一般以_info结尾)。 字节码文件中数据存放顺序是按照下面表中的顺序存放的,比如文件的开始位置会存放4个字节的数据,我们称之为magic。所以,在进行字节码分析时,我们可以参考下面的表进行对比分析。

 

magic(u4)的翻译是魔术,但是这里是魔数。这个魔数的作用就是文件标识,用来标识这是一个字节码文件可以被JVM加载运行。查看字节码开始的4个字节,我们会发现是fecababe。所有的字节码文件开始都是这样的。

minor_version(u2)紧跟着魔数有两个字节(0000)表示次版本号,次版本一般是JDK的某个分支如JDK 1.1有个分支为JDK1.1.8,那么此版本号就为0x0003。这个次版本号不太重要。

major_version(u2)接下来的两个字节(0033)表示主版本号,这个主版本号很重要。我们经常会看到用低版本的java编译器编译出来的class文件无法在高版本的虚拟机上运行就是因为JVM会查看这个值。0x0033的十进制是51表示这个class文件只能在JDK1.7以上的虚拟机中运行(版本号对应的JDK这里可自行百度)。

constant_pool_count(u2):记录常量池中常量的个数,002C的十进制为44,表示在常量池中有44个常量。因为常量的池的大小不固定,如果没有这个数的话JVM在加载常量池不知道需要申请多大的空间才合适。

constant_pool(cp_info):这就是我们所谓的常量池,我们看到常量池使用表来表示的。其原因就是常量池中存放的大量的数据,我们用最大的基本类型u8也只能表示8个字节,所以只能用表来描述这段区域了。下面就是常量池中能放的内容:字面量和符号引用。字面量就是我们定义的字符串,final常量等,而符号引用包括类和接口的全限定名,方法名和描述符,字段名和描述符。

  对常量池中存放的常量都是以表的方式来描述的。在每个表的开始位置是个tag(u1),用来表示该常量是什么。我们可以对应下面的表来分析常量池中的数据。

  我们开始对常量池进行分析

  第一个常量0a00 0a00 1a,我们查表发现。OA是一个表示常量池中第一个常量是方法的符号引用,紧跟着我们看到000a 和001a。通过查表我们发现这是两个索引。第一个索引指向的是一个CONSTANT_Class_info这种表的数据位置,第二个索引指向CONSTANT_NameAndTyep_info这种表数据位置。简单来说,000A指向常量池中第10个常量,而001a指向第26个常量。下面是第26个常量中放的内容。我们查表可以得到07表示一个对类描述的表,0025又是一个索引,这个索引指向第37个常量。

  第二个常量08 001b,通过查表(08)我们发现,第二个常量是字符串类型。他的第二个索引是001b(27),指向第27个常量。至于第27个常量中具体放的什么,这里就不做分析了。

  总结一下,我们观察了常量池中的前两个常量,第一个是方法,第二个是字符串。但是我们发现方法处并未显示有具体的方法,字符串处并未看到具体的字符,放到全是索引。这就是class文件的一个特点,先说有这个东西,具体是是什么请通过后面的索引去查找。下面我们借助java中的工具看看常量池中内容。

图1.1

通过工具我们可以直观的看到看到常量池中内容了。

  我们看到第一个常量是方法,这和我们分析的一样。常量中的数据是索引#10和#26。在#10处我们看到是一个Class常量,而Class中有个索引是#37.#37处的常量这里没有显示,但是通过后面的注释可以看到#37处放的是java/lang/Object字符串,存储类型是UTF8,表示类名。通过一步步查找我们可以知道,方法中的第一个常量是类名,表示这个方法属于哪个类,而“<init>”表明该方法的的名称,()V表示该方法的无参且返回值为void。那这个方法具体对应代码中的那个方法呢?其实就是我们从父类继承来的无参构造器。

  第二个常量是String类型,存储的数据是索引#27。而第27个常量处放的是Utf8类型,而内容为abc。这样就和我们的代码对应起来了,但是还一点就是这个字符串常量是被赋值给一个str属性的,这个str在哪里呢?

  第三个常量是Fieldref,我们看到它里面存的还是索引,而索引中的内容是UTF8类型的字符串。字符串的内容是 JavaMethodAreaOOM和str:Ljava/lang/String;这表示这个属性属于JavaMethodAreaOOM类的属性,而这个属性的类型是String类型。

  第四个常量也是Fieldref,这就是我代码中的int类型了。索引中存储的是JavaMethodAreaOOM和i:I,前者表示所属类,后者是名字和类型。i就是变量名而I就是int类型了。

常量池总结

量池中大的分类就是字面的量和符号引用。细化后就是字符串常量,索引值,类名,方法名,属性名,属性的类型,方法的参数,方法的返回值。而方法体以及一些其他属性的初始化操作(int=1)会放在class文件的代码区。

访问标志

常量池之后是访问标志(两个字节)了,这个访问标志了这个类的访问信息。包括是接口还是类,是否为public。下面是对访问标志的描述。

类索引,父类索引,接口索引

按照最开始的那张表来看,字节码文件中访问标志位后面的应该是类关系,主要记录该类叫啥,该类的父类是谁,该类实现的接口的数量以及具体的接口。下面是具体的内容。

  对照表6-6我们知道0009是一个u2类,转为十进制就是9,这个9其实是个索引,而这个索引指向的位置是常量区。通过查看图1.1发现,9的位置又是一个索引指向#36,而36的位置放的是字符串 JavaMethodAreaOOM,这就是这个类的类名了。000a十进制位10,而10的位置放的是索引37,37的位置的放的是java/lang/Object。0000表示该类实现的接口数量为0。

  通过以上分析,我们即使不看源代码,通过字节码文件就可以看出该类的关系图了。从这里我们也发现了索引存储的魅力(伟大的复用性)。

域描述

  域描述就是描述接口或类中定义的变量。对域的描述包括作用域(public,protected,private),是实例变量还是类变量(static),可变性(final),并发可见性(volatile),是否能被序列化(transient),字段类型(基本类型,对象,数组,),字段名称等等。这些内容都要在域描述中体现出来。

方法描述

  对于方法的描述和对域描述的方式几乎是一致的,都是采用下图中的描述方式。

access_flags:访问标志

name_index:方法名索引

descriptor_index:参数以及返回值类型索引

attribute_info:对于方法而言这里放的就是Code(代码了)

属性表

字节码文件最后放的就是属性表了。在域描述和方法描述中都提到了属性表。这里不做分析,我们只关心其中方法中的code内容,code从字面上看就是代码的意思。code中放的就是每个方法体被编译后生成的java指令。下图就是每个code的具体内容了。

关于字节码指令的解读放在下一章,这里我们只需要注意到test()方法是一个无参数函数,但是其code属性中显示参数的个数(args_size=1)。这个1表示的其实是this这个参数。我们之所以能在方法内使用this就是因为jvm在加载类时会为每个方法自动传入一个this参数。

class文件概述的更多相关文章

  1. .edmx 文件概述(实体框架)

    (一) 认识.edmx文件结构 参考资料: .edmx 文件概述(实体框架) Entity Framework 全面教程详解(转) Entity Framework 教程 Entity Framewo ...

  2. Java编程的逻辑 (56) - 文件概述

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  3. sid-msg.map文件概述

    我这边编写了magic对应的指定文件规则,但是运行的时候发现储存的文件中包含我未指定的数据文件: 在rules下边看的时候,发现有sid-msg.map文件,上网了解下这个文件是干啥的.. 下边文章来 ...

  4. ORACLE初始化参数文件概述

    ORACLE初始化参数文件概述 在9i之前,参数文件只有一种,它是文本格式的,称为pfile,在9i及以后的版本中,新增了服务器参数文件,称为spfile,它是二进制格式的.这两种参数文件都是用来存储 ...

  5. Linux下通过.desktop 文件创建桌面程序图标及文件编写方式(Desktop Entry文件概述)

    Linux下通过.desktop 文件创建桌面程序图标及文件编写方式 1.Desktop Entry文件概述:在 Windows 平台上,用户可以通过点击位于桌面或菜单上的快捷方式轻松打开目标应用程序 ...

  6. 【JAVA 文件概述】

    一.概述 使用此类的原因: 该类将文件或者文件夹封装成对象.方便对文件与文件夹的属性信息进行操作.File对象作为参数传递给流的构造函数.要求:使用File类的常用方法. windows平台下,目录分 ...

  7. 一、MP3文件概述

    一.概述 MP3 文件是由帧(frame)构成的,帧是 MP3 文件最小的组成单位.MP3 的全称应为 MPEG1 Layer-3 音频文件,MPEG(Moving Picture Experts G ...

  8. cocos2d-x游戏开发系列教程-中国象棋01-工程文件概述

    上一篇博文我们看到了象棋的效果图,这一张我们来看象棋代码的整体概述 让我们先对整个代码框架有个了解. 主目录: 主目录包含内容如上图: classes目录:业务代码 proj.win32:包括main ...

  9. Spring---配置文件概述

    概述 Spring 的配置文件是用于指导 Spring 工厂进行Bean的生产.依赖关系注入及 Bean 实例分发的“图纸”,它是一个或多个标准的XML文档,J2EE 程序员必须学会并灵活应用这份“图 ...

随机推荐

  1. mysql IP转换函数

    1.将字符串类型的实际IP转换成十进制数值型的 SELECT INET_ATON('209.207.224.40'); 执行结果:

  2. Windows10 利用 Docker 配置 TensofFlow 深度学习工具

    TensorFlow 这个不用多介绍了吧,大家都知道,Google的开源深度学习软件库,官网点这里:https://www.tensorflow.org/ 当然这个工具官方支持装在 Ubuntu 和 ...

  3. x01.Excel: 合计件数

    由于 VBA 与 Excel 是耦合的,所以还是先看表: 件数的计算,用 Mod 即可.但考虑到要求码洋.数量等多种需求,就该 VBA 登场了.代码如下: '===================== ...

  4. ubuntu下eclipse scala开发插件(Scala IDE for Eclipse)安装

    1. 环境介绍 系统:ubuntu16.04(不过和系统版本关系不大) elipse:Neon.1aRelease (4.6.1) 2. 插件介绍 Scala IDE for eclipse是elip ...

  5. 磁盘配额-----quota

    为什么要使用磁盘配额:为了限制普通用户使用普通磁盘的空间与创建文件的个数等. 不至于个别人的浪费影响所有人的使用. 需要安装quota的软件包. mount -o usrquota,grpquota ...

  6. 为什么是 Cloud Service?

    怀旧一把,还记得这个界面吗? 没错,这是第一版Windows Azure Management Portal,用Silverlight开发的,很炫! 奇怪,为什么没有Virtual Machine? ...

  7. [转]net中哈希表的使用 Hashtable

    本文转自:http://www.cnblogs.com/gsk99/archive/2011/08/28/2155988.html 以下是PetShop中DBHelper中的使用过程: //创建哈希表 ...

  8. appium 常用api介绍(1)

    前言:android手机大家都很熟悉,操作有按键.触摸.点击.滑动等,各种操作方法可以通过api的方法来实现. 参考博文:http://blog.csdn.net/bear_w/article/det ...

  9. CKEDITOR最新版不能上传图片的解决

    文献:http://bbs.csdn.net/topics/390883077 代码例子:http://download.csdn.net/download/itmyhome/7851265 1.原先 ...

  10. 分布式系统理论之Quorum机制

    一,Quorum机制介绍 在分布式系统中有个CAP理论,对于P(分区容忍性)而言,是实际存在 从而无法避免的.因为,分布系统中的处理不是在本机,而是网络中的许多机器相互通信,故网络分区.网络通信故障问 ...