天天看点

Java Class字节码知识点回顾

把之前的笔记重新整理了一下,发上来供对java class文件结构的有兴趣的同学参考一下,也算对以前知识的回顾。

java class文件打破了c或者c++等语言所遵循的传统,用这些传统语言写的程序通常首先被编译,然后被连接成单独的、专门支持特定硬件平台和操作系统的二进制文件。通常情况下,一个平台上的二进制可执行文件不能在其他平台上工作。

java class文件是可以运行在任何支持java虚拟机的硬件平台和操作系统上的二进制文件,class文件中包含了java虚拟机指令集和符号表以及若干其他辅助信息。作为一个通用的、机器无关的执行平台,任何其他语言的实现者都可以将java虚拟机作为语言的产品交付媒介。例如,使用java编译器可以把java代码编译成存储字节码的class文件,使用grooy等其他语言的编译器一样可以把程序代码编译成class文件,虚拟机并不关心class的来源是何种语言。

Java Class字节码知识点回顾

class文件是一组以8位字节位基础单位的二进制流,采用一种类似c语言结构体的伪结构来存储数据,这种伪结构只有两种数据类型:<code>无符号数</code>和<code>表</code>。无符号数属于基本的数据类型,以u1、u2、u4、u8分别代表1个字节、2个字节、4个字节、8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或utf-8编码构成的字符串值。表是由多个无符号数或其他表作为数据项构成的复合数据类型,所有表都习惯性地以_info结尾。

每一个 class 文件对应于一个如下所示的 classfile 结构体:

借用下之前同学的图能更清晰地表达:

Java Class字节码知识点回顾

本文以testclasscode.class源码为例展开,testclasscode.java对应的java代码如下:

testclasscode.class对应的字节码如下:

constant pool:

#1 = class #2 // com/test/doc/exp/testclasscode

#2 = utf8 com/test/doc/exp/testclasscode

#3 = class #4 // java/lang/object

#4 = utf8 java/lang/object

#5 = utf8 attribute_1

#6 = utf8 ljava/lang/string;

#7 = utf8 attribute_2

#8 = utf8 ljava/lang/integer;

#9 = utf8

#10 = utf8 ()v

#11 = utf8 code

#12 = methodref #3.#13 // java/lang/object."":()v

#13 = nameandtype #9:#10 // "":()v

#14 = utf8 linenumbertable

#15 = utf8 localvariabletable

#16 = utf8 this

#17 = utf8 lcom/test/doc/exp/testclasscode;

#18 = utf8 testinterface_1

#19 = utf8 testinterface_2

#20 = utf8 (ljava/lang/string;)ljava/lang/string;

#21 = utf8 param

#22 = utf8 sourcefile

#23 = utf8 testclasscode.java

struct field_info {

u2 access_flags;

u2 name_index;

u2 descriptor_index;

u2 attributes_count;

attribute_info attributes;

}

struct method {

u2 method_counts;

method_info[] method_infos;

struct method_info {

struct attribute_info {

u2 attribute_name_index;

u4 attribute_length;

u1 info[attribute_length];

struct code {

u2 max_stack;

u2 max_locals;

u4 code_length;

u1 code[code_length];

u2 exception_table_length;

exception_info exception_table;

u2 attribute_count;

struct linenumbertable {

u2 line_number_table_length;

line_number_info line_number_table;