`

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

 

大功告成!

 

分享到:
评论

相关推荐

    java8看不到源码-jvms-compare:JVM比较-使用基准

    java8 看不到源码JVM 比较 JVM 比较 - 使用基准 该存储库承载了一些作为具有不同配置文件的 Maven 项目运行的单元测试。 单元测试依赖于库并使用 JMH 作为基准。 各种配置文件旨在在不同的 ...版本,已

    WindowsJDK版本管理器jvms.zip

    JDK Version Manager (JVMS) for Windows Windows下JDK多版本管理器,类似 nvm, nvmw, rvm 本软件源于 nvm-windows , 现在是第一版 .  这对JDK不同版本之间切换是非常有用的。例如,如果你想测试一个...

    Windows的JDK版本管理器(JVMS)-Golang开发

    Windows的JDK版本管理器(JVMS)在Windows计算机上管理JDK的多个安装。 JVMS,立即下载! 在某些情况下,能够在不同版本的JDK之间进行切换非常有用。 对于Windows的前JDK版本管理器(JVMS)在Windows计算机上管理JDK...

    JVM原理之运行时数据区详解

    关于运行时数据官方解释:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5 4.1 堆 (heap) 堆在虚拟机中是一块共享区域, 存放 对象实例 和数组; 堆在虚拟机启动的时候创建。 可调整堆的...

    jvms13.pdf

    The Java® Virtual Machine Specification Java SE 13 Edition Tim Lindholm Frank Yellin Gilad Bracha Alex Buckley Daniel Smith

    jvms12.pdf(Java虚拟机规范 JDK12版)

    Java虚拟机规范 JDK12版,Java开发者必须要看的文档。文档为英文版,更有利于理解作者的原意。

    jls8英文文档 jvms8英文文档

    jls英文文档 jvms英文文档

    jvms12.pdf

    java虚拟机规范,java12版本。可以了解java虚拟机的设计。

    ClassViewer v3是轻量级的Java类文件查看器,仅依赖JDK和JavaFX-Android开发

    ClassViewer网站:ClassViewer主页ClassViewer v3是一个轻量级Java类文件查看器,仅依赖JDK和JavaFX,它只有一个小于250k的jar文件,并且可以在JRE 8上运行。OracleJDK不再是ClassViewer网站:ClassViewer主页Class...

    jvms7

    jvm

    jdk-8u361-windows-x64.exe

    它实现了 Java 语言规范 (JLS) 和 Java 虚拟机规范 (JVMS),并提供了 Java 应用程序编程接口 (API) 的标准版 (SE)。它是Oracle监管者社区驱动的OpenJDK的衍生物。[5]它提供了用于处理Java应用程序的软件。所...

    jdk-8u331-windows-x64.exe

    它实现了 Java 语言规范 (JLS) 和 Java 虚拟机规范 (JVMS),并提供了 Java 应用程序编程接口 (API) 的标准版 (SE)。它是Oracle监管者社区驱动的OpenJDK的衍生物。[5]它提供了用于处理Java应用程序的软件。所...

    Java虚拟机规范_SE8版

    Java虚拟机规范_SE8版 链接: https://pan.baidu.com/s/1dOSFmu

    JDK版本切换

    windows环境下的JDK1.7与1.8版本自由切换,非常的方便和使用。

    jna-4.2.2 官方原版下载

    Supported on 1.4 or later JVMs, including JavaME (earlier VMs may work with stubbed NIO support) Customizable marshalling/unmarshalling (argument and return value conversions) Customizable mapping ...

    Java语言规范和JVM规范(7、8、9)

    包含Java SE7、8、9的语言规范和虚拟机规范,Oracle官方文档,可以去官网下载:https://docs.oracle.com/en/java/index.html

    jacob-1.19.zip

    COM Bridge that allows you to call COM Automation components from Java. It uses JNI to make native calls to the COM libraries. JACOB runs on x86 and x64 environments supporting 32 bit and 64 bit JVMs

    jsr133_content.pdf

    Virtual Machine Specification (JVMS), and the specification for classes in the java.lang package. This JSR-133 specification will not be further maintained or changed through the JCP. All future ...

    jdk-12_osx-x64_bin.tar.gz

    在新的 java.lang.invoke.constant 包中定义了一系列基于值的符号引用(JVMS 5.1)类型,它们能够描述每种可加载常量。符号引用以纯 nominal 形式描述可加载常量,与类加载或可访问性上下文区分开。有些类可以作为...

    Android代码-Smack

    Smack is an open source, highly modular, easy to use, XMPP client library written in Java for Java SE compatible JVMs and Android. A pure Java library, it can be embedded into your applications to ...

Global site tag (gtag.js) - Google Analytics