`
bolinyang
  • 浏览: 74194 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java的class文件结构介绍以及如何实现javap

    博客分类:
  • JVM
JVM 
阅读更多
一.概述

      我们在写JAVA程序的时候,面对的都是.java文件的编写,但是JVM不会直接拿.java文件去执行的,对于JVM而言,它只认识.class文件,那么是不是后缀名是.class的文件JVM都会接收呢?显然不是,因为要想JVM接受一个.class文件,这个.class文件必须要有严格的结构,这样JVM才会识别这个.class文件,并且按照.class文件去做一些事情。
      我们写的.java文件首先要经过JAVA编译器的编译,这时候编译的结果就是.class文件,JAVA语言有它自己的语法产生式,编译的时候,首先对源程序进行此法分析,然后再在词法分析的基础上按照JAVA语言自己的语法产生式进行语法分析,语法分析的目的是按照产生式对源程序(这里源程序其实就是一个字符串)进行一系列推导,比如,最左推导,最右推导等等,如果无法按照产生式推导出这个字符串,这就说明源程序有语法错误。如果源程序没有语法错误,此时JAVA编译器就是生成目标代码,其实就是.class文件,这时候这个.class文件有非常严格的结构,能够被JVM所识别,其实.class文件就是javac的结果,同样也有一个javap命令可以实现反编译,javap可以把一个.class文件中各个结构清晰的打印出来,方便开发人员和.java文件进行对比。假如有一个Test.class文件,我们是由javap -verbose Test就可以看到这个class文件各个部分的具体结构了。这里的主要目的就是分析class文件的结构以及怎么去实现一个javap这样的命令。



上图是针对上面描述的一个图示概述

二.class文件的整体数据结构


      通过观察上图,我们发现java源程序中的所有信息都可以在class文件中体现出来(注释除外),每个class文件最后都有一些附加属性,这些附加属性是针对这个class的描述。比如当前class对应的源程序文件名称,当前class的内部class等等都属于class的附加属性,出现在class文件的最后。

下面我们给出class文件的数据结构表,可以参考http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
类型名称数量
u4magic(魔数)1
u2minor_version(版本号之小版本号)1
u2major_version(版本号之主版本号)1
u2constant_pool_count(常量池中常量的数目)1
cp_infoconstant_pool(常量池)constant_pool_count - 1
u2access_flags(当前类的访问权限标记)1
u2this_class(当前类的相关描述信息)1
u2super_class(当前类超类的描述信息)1
u2interfaces_count(当前类实现的接口数目)1
u2interfaces(当前类实现了那些接口)interfaces_count
u2field_count(当前类的字段数目)1
field_infofields(当前类的字段)field_count
u2method_count(当前类的方法数目)1
method_infomethods(当前的方法)method_count
u2attributes_count(当前类的附加属性数目)1
attribute_infoattributes(当前类的附加属性)attributes_count

注:

1.上述数据结构中既有无符号数,也有表,所有的表都以_info结尾,表用于描述有层次关系的复合数据结构,无论是无符号数还是表,当需要描述同一类型但数量不定的多个数据时,经常会使用一个前置容量计数器加若干连续的数据项的形式,这时候称这一系列连写的某一类型的数据为某一类型的集合。


2.对于class文件的这么多结构,其实一开始没有必要担心的也没有必要仔细去深究这些结构的之间的关系,先有个大致的了解,慢慢往后一个一个数据结构去理解,最后再回过头来看看这些数据结构,你就能理解他们之间的关系,以及表的内部是如何组织的了。

三.魔数和版本号的解析

1.关于魔数的解析
     在.class文件的开头四个字节就是.class文件的魔数,这个魔数决定了这个.class文件能否被JVM虚拟机所加载。首先读取这个字节数组,这个字节数组大小是4,然后把这个字节数组转换成一个十六进制的数字,看看这个十六进制的数字是不是0XCAFFEEBABE,如果这个字节数组对应的十六进制数是0XCAFFEEBABE,这时候这个.class文件就可以被JVM所加载,否则这就是一个非法的.class文件。在这里需要注意的是一个字节表示8个二进制为,那么四个字节就是32个二进制位了。


2.关于版本号的解析
     紧接着魔数后面就是版本号,这个版本号其实和JDK的版本有关,分为次版本号和主版本号,各占一个字节,把这个字节转换成十进制数字,就可以看到版本号是多少了。


3.关于魔数和版本号的解析,说白了就是字节数组到十六进制或者十进制数值之间的转换。


4.下面用vi打开一个.class文件,然后使用%!xxd切换到十六进制显示,可以看看魔数和版本号


四.常量池的解析

1.关于常量池的概述
     常量池是一个很重要的部分,首先从字面意思来理解,常量即不变,池说明是一个容器,在这个容器中存放的都是一些不变的量,把这些不变的量集中在一个地方,方便其他模块引用,这也是写程序时的一个基本理念。在常量池中主要存放了两大类常量:字面量(Literal)和符号引用(Symbolic Reference)。字面量比较接近JAVA语言层面的常量,如文本字符串,被定义为final类型的常量值等等。而符号引用和编译原理有关,编译JAVA代码的时候需要一个符号表,这个符号表中存储了对于方法和字段以及类描述等信息。每个方法都有一些固定的属性,例如方法名称,返回值类型,入参类型等等,这些信息在编译的过程存储在符号表中,在CLASS文件中就体现在常量池中。


2.常量池中内容概述图



未完待续
  • 大小: 37.9 KB
  • 大小: 60.1 KB
  • 大小: 38.1 KB
分享到:
评论

相关推荐

    JAVA上百实例源码以及开源项目

     Java编写的网页版魔方游戏,编译后生成.class文件,然后用HTML去调用,不过运行时候需要你的浏览器安装有运行Class的插件。Java源代码实现部分,比较有意思,也具参考性。像坐标控制、旋转矩阵、定时器、生成图像...

    javaclass和源码-deep-in-jvm:简单的借助jdk中的内置工具帮助我们对比Java源码和生成的字节码以及探究Class文件字节

    简单的借助jdk中的内置工具帮助我们对比Java源码和生成的字节码以及探究Class文件字节码结构 使用方法 编写Java源码,如项目目录中的Main.java: 运行javac编译成字节码 javac -g:vars Main.java 编译生成...

    JAVA上百实例源码以及开源项目源代码

     Java编写的网页版魔方游戏,编译后生成.class文件,然后用HTML去调用,不过运行时候需要你的浏览器安装有运行Class的插件。Java源代码实现部分,比较有意思,也具参考性。像坐标控制、旋转矩阵、定时器、生成图像...

    自己动手实现一个Java Class解析器

    实际上JDK已经提供了命令行工具javap来反编译Class文件,但本篇文章将阐明我实现解析器的思路。  Class文件  作为类或者接口信息的载体,每个Class文件都完整的定义了一个类。为了使Java程序可以“编写一次,...

    java开源包4

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包3

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包11

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包6

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包101

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包9

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包5

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包8

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包10

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    深入JVM内核 - 原理、诊断与优化

    介绍JVM规范中的最重要的内容——Class文件结构,同时介绍ASM库的使用以及对class文件的修改。 第十一课 字节码执行 案例以及javap JIT及相关参数 介绍JVM的字节码以及反汇编方法,同时介绍JIT相关的参数和应用。

    java开源包1

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包2

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    java开源包7

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

    Java资源包01

    JReloader 是一个用来重新加载class文件而无需重启JVM的工具。 PHPJava Bridge php调用java类 Java批量作业执行框架 MyBatchFramework MyBatchFramework 是一个开源的轻量级的用以创建可靠的易管理的批量作业的...

Global site tag (gtag.js) - Google Analytics