JVMS- class File Format-走一遍 【转载】

CHAPTER 4 The class File Format

这一章从来就没有认真看过,今天看了几个小时,头都大了。12.29号继续。

 

1、自己动手查看.class文件的16进制、10进制和char表示。编写一个最简单的C程序就行了。

程序目标:输入当前目录中的.class文件(不要输入.class后缀),其他表示保存到文件byteCode.txt中。

程序1.exe:只要16进制的表示。

程序2.exe:方便起见,对照察看16进制、10进制表示。

程序3.exe:方便起见,对照察看16进制、10进制和char表示。其代码如下 

#include <stdio.h>
#include <string.h>
void main(){
 FILE *fpr, *fpw; int i;
 char str[80];
 printf("enter .class file name:\n");
 scanf("%s",str);
 char ext[8]={".class"};
 strcat(str,ext);
 fpr = fopen(str,"rb");
 fpw = fopen("byteCode.txt","wb+");
 while ((i=fgetc(fpr)) != EOF){
  fprintf(fpw,"%x\t%d\t%c\n",i,i,i);
 }
 fclose(fpr);fclose(fpw);
}

 

2、写一个最没有用的Java程序AAA.java

public class AAA{
}

编译成.class,执行1.exe后得到byteCode.txt。

ca fe ba be 0 0 0 32 0 10 a 0 3 0 d 7 0 e 7 0 f 1 0 6 3c 69 6e 69 74 3e 1 0 3 28 29 56 1 0 4 43 6f 64 65 1 0 f 4c 69 6e 65 4e 75 6d 62 65 72 54 61 62 6c 65 1 0 12 4c 6f 63 61 6c 56 61 72 69 61 62 6c 65 54 61 62 6c 65 1 0 4 74 68 69 73 1 0 5 4c 41 41 41 3b 1 0 a 53 6f 75 72 63 65 46 69 6c 65 1 0 8 41 41 41 2e 6a 61 76 61 c 0 4 0 5 1 0 3 41 41 41 1 0 10 6a 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a 65 63 74 0 21 0 2 0 3 0 0 0 0 0 1 0 1 0 4 0 5 0 1 0 6 0 0 0 2f 0 1 0 1 0 0 0 5 2a b7 0 1 b1 0 0 0 2 0 7 0 0 0 6 0 1 0 0 0 1 0 8 0 0 0 c 0 1 0 0 0 5 0 9 0 a 0 0 0 1 0 b 0 0 0 2 0 c

A class file consists of a stream of 8-bit bytes. 每字节一行,这个byteCode.txt有234多行,yqj2065要byte by byte 的看看这些东西。过一遍后,再用jclasslib学习较复杂的例子。

 

3、The class File Format

Each class file contains the definition of a single class or interface.所以.class文件要表示该类/接口的种种info,使用了u1, u2, and u4 (class文件的)类型和类似C结构的pseudostructures如ClassFile、cp_info 、field_info 、method_info 和attribute_info 等等。

 

byte by byte

一个class文件由单一的 ClassFile structure构成。

    ClassFile {
     u4 magic;
     u2 minor_version;
     u2 major_version;
     u2 constant_pool_count;
     cp_info constant_pool[constant_pool_count-1];
     u2 access_flags;
     u2 this_class;
     u2 super_class;
     u2 interfaces_count;
     u2 interfaces[interfaces_count];
     u2 fields_count;
     field_info fields[fields_count];
     u2 methods_count;
     method_info methods[methods_count];
     u2 attributes_count;
     attribute_info attributes[attributes_count];
    }

1、前10个字节。

ca fe ba be 0 0 0 32 0 10

传说中的u4 magic,值为0xca fe ba be读作cafe babe,为什么不是Jame sGos(ling )。

0 0 0 32 //u2 minor_version, u2 major_version 分别是0x0,0x32即50,version0.50

0 10 // u2 constant_pool_count 这一项的值有16.constant_pool[]中有16-1 ==15项

 

2、cp_info部分。The constant_pool is a table of structures (§4.4) representing various string constants, class and interface names, field names, and other constants that are referred to within the ClassFile structure and its substructures.基本形式为:

    cp_info {
     u1 tag;
     u1 info[];//这个部分随着tag值不同,由对应项替换。
    }

------------------constant_pool[]--------------------

对照察看16进制、10进制表示:

a 10  u1 tag 查表10对应CONSTANT_Methodref(10 ),随后的u2+u2是CONSTANT_Methodref_info

0 0 
3 3 
0 0 
d 13

方便起见,现在开始用伪结构表示。使用10进制表示(如果是16进制,按惯例加以前缀0x)

  CONSTANT_Methodref_info { //#1 index in constant_pool[]
     u1 tag;                // 10 ->CONSTANT_Methodref
     u2 class_index;        // 0 3 指向#3constant_pool[]实体
     u2 name_and_type_index;// 0 13 指向#13constant_pool[]实体
   }//参见4.4.2

 

 

 

   CONSTANT_Class_info {  //#2
     u1 tag;           //7
     u2 name_index;    //0 14 指向constant_pool[]中的#14实体
   }

   CONSTANT_Class_info { //#3
     u1 tag;           //7
     u2 name_index;    //0 15
   }

接下来,要对照察看16进制、10进制和char表示了。因为是CONSTANT_Utf8_info Structure。

1 1 
0 0 
6 6 
3c 60 <
69 105 i
6e 110 n
69 105 i
74 116 t
3e 62 >

    CONSTANT_Utf8_info { //#4
     u1 tag;       //1
     u2 length;     //0 6 byte数组中有6个字符
     u1 bytes[length];// 0x3c 69 6e 69 74 62 即<init>
    }

    CONSTANT_Utf8_info {//#5
     u1 tag;       //1
     u2 length;     //0 3 
     u1 bytes[length];//  ()V
    }

同样,#6即Code、#7即LineNumberTable,#8即LocalVariableTable,

#9即this,#10即LAAA; ,#11即SourceFile,#12即AAA.java

 

    CONSTANT_NameAndType_info {#13
     u1 tag;  //12
     u2 name_index; // 0 4 即指向#4的<init>
     u2 descriptor_index; //0 5 即()V
    }
CONSTANT_Utf8_info:#14即AAA、#15即java/lang/Object //共15个

The constant_pool table is indexed from 1 to constant_pool_count-1.

------------------constant_pool[]--------------------

 

3、中间若干项,看ClassFile structure那个大图。

接下来是u2 access_flags;直到u2 methods_count;

0 0 
21 33 //u2 access_flags;值为0x0021 

       //即0x0020 |0x0001,也就是ACC_SUPER和ACC_PUBLIC 。AAA是public

0 0 
2 2  //u2 this_class; 值为2指向constant_pool[]中的#2,后者指向#14,即AAA 
0 0 
3 3 //u2 super_class; //#3->#15即java/lang/Object 
0 0 
0 0  //u2 interfaces_count; 值为0x00 00,没有下一项。
     u2 interfaces[interfaces_count];
0 0 
0 0  //u2 fields_count;
     field_info fields[fields_count];
0 0 
1 1  //u2 methods_count;值为0x00 01,一个方法

 

4、method_info。参考4.6 Methods

Each method, 包括each instance /the class or interface initialization method (§3.9), 都由a method_info structure说明. No two methods in one class file may have the same name and descriptor (§4.3.3).在4.3.3 Method Descriptors中说明了一般格式:

    ( ParameterDescriptor* ) ReturnDescriptor

基本形式为:

    method_info {
     u2 access_flags;
     u2 name_index;
     u2 descriptor_index;
     u2 attributes_count;
     attribute_info attributes[attributes_count];
    }

这个部分字节如下:

0 0   
1 1  //u2 access_flags;0 1 即ACC_PUBLIC 
0 0 
4 4  //u2 name_index; 0 4 指向constant_pool[]中的#4,即<init> 
0 0 
5 5  //u2 descriptor_index; 0 5 指向#5即()V 表示void 
0 0 
1 1 //u2 attributes_count; 0 1表示有一个属性。转入attribute_info结构。

   

5、attribute_info,参考4.7 Attributes

这个attributes广泛用于the class file format中的ClassFile, field_info , method_info 和 Code_attribute (§4.7.3) structures 。一般形式为:

   attribute_info {
     u2 attribute_name_index;
     u4 attribute_length;
     u1 info[attribute_length]; //随着attribute_name_index不同由由对应项替换。
    }

由于我们这里遇到的是4.7.3 The Code Attribute,使用Code_attribute 。

    Code_attribute {
     u2 attribute_name_index;
     u4 attribute_length;
     u2 max_stack;
     u2 max_locals;
     u4 code_length;
     u1 code[code_length];
     u2 exception_table_length;
     {    u2 start_pc;
           u2 end_pc;
           u2  handler_pc;
           u2  catch_type;
     } exception_table[exception_table_length];
     u2 attributes_count;
     attribute_info attributes[attributes_count];
   }

这个部分字节如下:
0 0 
6 6 //u2 attribute_name_index; 0 6即Code所有的方法/构造器都有这个属性 
0 0 
0 0 
0 0 
2f 47 //u4 attribute_length;47 下面的47字节属于本attribute

0 0 
1 1 //u2 max_stack; 0 1
0 0 
1 1 //u2 max_locals。0 1 
0 0 
0 0 
0 0 
5 5 //u4 code_length;下面的5字节属于本Code  
2a 42 
b7 183 
0 0 
1 1 
b1 177 //code[5]; 0x 2a b7 00 01 b1 是什么东西?
0 0 
0 0 //u2 exception_table_length; 没有exception_table
0 0 
2 2 // u2 attributes_count;嵌套了2个属性。

 

A Code attribute 常常有自己的属性,Currently, the LineNumberTable (§4.7.8) and LocalVariableTable (§4.7.9) attributes, both of which contain debugging information, are defined and used with the Code attribute.

    LineNumberTable_attribute {
     u2 attribute_name_index;
     u4 attribute_length;
     u2 line_number_table_length;
     {  u2 start_pc;     
        u2 line_number;     
     } line_number_table[line_number_table_length];
    }

0 0 
7 7 //u2 attribute_name_index; 0 7 #7即LineNumberTable 
0 0 
0 0 
0 0 
6 6 //u4 attribute_length;下面的6字节属于本attribute 
0 0 
1 1 //u2 line_number_table_length;即line_number_table[1]; 
0 0 
0 0 //u2 start_pc;  
0 0 
1 1 //u2 line_number;

 

又一个嵌套属性

    LocalVariableTable_attribute {
     u2 attribute_name_index;
     u4 attribute_length;
     u2 local_variable_table_length;
     {  u2 start_pc;
         u2 length;
         u2 name_index;
         u2 descriptor_index;
         u2 index;
     } local_variable_table[local_variable_table_length];
   }

0 0 
8 8 //u2 attribute_name_index; 0 8 #8即LocalVariableTable  
0 0 
0 0 
0 0 
c 12 //u4 attribute_length;下面的12字节属于本attribute
0 0 
1 1 //u2 local_variable_table_length;即local_variable_table[1]; 
0 0 
0 0 //u2 start_pc; 
0 0 
5 5 //u2 length; 
0 0 
9 9 //u2 name_index; #9即this
0 0 
a 10 //u2 descriptor_index; #10即LAAA;
0 0 
0 0 //u2 index;

 

6、最后是4.7.7 The SourceFile Attribute

  SourceFile_attribute {
     u2 attribute_name_index;
     u4 attribute_length;
     u2 sourcefile_index;
   }
0 0 
1 1 //看ClassFile structure那个大图。u2 attributes_count;本class文件的属性1个。
0 0 
b 11 //u2 attribute_name_index;#11即SourceFile
0 0 
0 0 
0 0 
2 2 //u4 attribute_length;
0 0 
c 12 //u2 sourcefile_index;#12即AAA.java

 

大功告成!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值