`

11、字节码文件解析

 
阅读更多

         实现语言与操作系统的无关性基础仍然是虚拟机和字节码储存格式,jvm不与java及其他任何语言绑定,只和.class文件这种特定的二进制格式绑定, class文件包含jvm的指令集和符号表等其他信息;使用javac可以将java语言编译成.class文件,使用JRuby编译器可以讲JRuby编译成.class文件,jvm并不关心.class的来源是何种语言。

 

        .class字节码命令提供的描述能力比java语言本身还要强大;.class文件是一组以8位字节(64位)为基础的二进制流,中间没有任何分隔符(如逗号,句号,换行等);jvm规定:.class文件采用一种类似c语言结构体的伪结构来储存数据,这种伪结构只有两种数据类型:无符号数和表

        无符号数属于基本的数据类型,以u1,u2,u4,u8来分别表示一个字节,两个字节,四个字节和8个字节的无符号数,无符号数用来描述数字,索引引用,数量值或按照UTF8编码构成字符串数;

        表是由多个无符号数或其他表作为数据项构成的复合数据类型,所有表都习惯性的以"_info"结尾,表用于描述有层次关系的复合结构的数据。整个CLASS文件本质上是一张表。

一个字节码文件大楷内容:

在一个class文件中,同一类型的数据前都会有个计数器,通过上图查看各个数据类型所占的长度。 

这是一个等待编译的接口:

package org;
public interface Demo {}

 执行编译后,执行javap -berbose Demo

E:\side1\Smart\src\test\java\org>javap -verbose Demo
Warning: Binary file Demo contains org.Demo
Classfile /E:/side1/Smart/src/test/java/org/Demo.class
  Last modified 2014-10-19; size 93 bytes
  MD5 checksum 43c458c35524acf338255261e9495239
  Compiled from "Demo.java"
public interface org.Demo
  SourceFile: "Demo.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
Constant pool:
  #1 = Class              #5              //  org/Demo
  #2 = Class              #6              //  java/lang/Object
  #3 = Utf8               SourceFile
  #4 = Utf8               Demo.java
  #5 = Utf8               org/Demo
  #6 = Utf8               java/lang/Object
{
}

打印了类文件路径、源文件、版本、md5、类文件长度(size)、类型标识和常量池内容;

使用WinHex软件打开这个类文件:

 

1、魔数和版本

从长度上为93个字符,是将class文件的二进制数组转换为16进制数组,

前4个字节称为魔数(0xCAFEBABE) ,现在很多文件采用魔数来识别文件类型,而不使用扩展名;

第5、6、7、8个字节是版本号,56是次版本号,78(0x0000 0000 67)是主版本号33,查到33对应的是51;

2、常量池

第9、10(0x0000 0000 89)是显示有多少个常量,这里显示的是7个,要减去一个;表示有6个常量,因为常量是从1开始索引而读取时从0开始读取的;

如果是26则表示(2*16+6-1)为37个常量;

常量池存放两种类型的常量:字面值(直接赋值如“ok”,23,literal)、符号引用(接口类的引用、方法的引用、字段?)

第A (11)字节表示该类文件是 是一个什么类型的引用:7 表示是一个类或接口的符号引用;

 


 
查看constant_class_info是含有u1,u2字节的,u1表示自己占了一个字节,u2表示后面的2个字节(0xBC)是显示这个calss或接口信息的 ,

0xC的值是5,表示指向常量池中的第#5项,为 #5 = Utf8 org/Demo,如果是类的值是2,#6是object;

0xD的值又是7,同上查6-3,但后面F的值是6,表示一个Object

到0x0000 00010 0,的值是1,查6-3,是constant_utf8_info,查6-6,要占4个字节,length:0A(10),打印的是sourcefile 10个字符,后又为1,值为9打印的是Demo.java

长度为9,后又为1,值为8,打印的是org/Demo长度为8,后有为1,值为10(16),打印java/lang/object长度为16;在74之后即字符t之后接着的2个字符0601表示访问标识符acess_flag,从javap中可以看到: flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT

0x0001|0x0200|0x0400  ---> 0x0601 就是这么来的;一般的类为flags: ACC_PUBLIC, ACC_SUPER,为21

  • 大小: 208.5 KB
  • 大小: 187.8 KB
  • 大小: 251.4 KB
  • 大小: 112.6 KB
  • 大小: 171.8 KB
  • 大小: 170.9 KB
  • 大小: 204.7 KB
  • 大小: 112.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics