http://www.i170.com/Forum/113657
花了10多个小时,才将JVMS- class File Format-走一遍 ,虽然针对的是最简单的AAA。意义何在?
1、对class文件格式有了整体认识,看CHAPTER 4 The class File Format已经是简单的事情了;
2、使用字节码察看工具,知道了其各项的对应关系。
3、补了一课,解开了一个心结。
CHAPTER 4 The class File Format
pseudostructures:在class文件中是不存在的,一种方便的说明方式。它有多个items,Successive items are stored in the class file sequentially, without padding or alignment. 所以,有一些说明本结构长度的项,如constant_pool_count等等各种xxx_count。
Tables是varying-sized structures ,而an array有fixed-sized items 。
4.1 The 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];
}
这个大图分7段,核心在cp_info 、field_info、method_info和多处使用的attribute_info。
本节比较重要的部分:
1、前10字节:JDK1.0.2中编译的class文件版本号为3.45,version0.50。
2、u2 constant_pool_count 最基本的值为16(事实上15项),其中第0项被隐藏。添加一些代码后,可以研究一下cp_info的变动情况。constant_pool table的排列有一定的顺序。这是重点。
3、中间字节:类的access_flags ,各种修饰符求或;this_class、super_class等等信息都要在constant_pool中找。
4、field_info、method_info和attribute_info,添加一些代码后使用jclasslib研究一下。
4.2 The Internal Form of Fully Qualified Class and Interface Names
class文件总是采用fully qualified form 的类型名,所以import语句都是语法糖;java.lang.Object转成了/分割。
4.3 Descriptors
A descriptor using UTF-8 strings (§4.4.7)表示the type of a field or method.
4.4 The Constant Pool
严格地,class文件中只有constant_pool table,而常量池是运行期的一个内存空间。当然JVM 指令不依赖类/接口/类实例/数组在运行时的布局,仅仅依赖于本constant_pool table中的字符信息(symbolic information )。
各种constant_pool table实体/条目(entries)由一个u1即1-byte tag来区别,以便使用相应的结构。
public class Yqj{
public static int i = 5;
private final double doo = 5.2;
String str = "hello";
public Object foo(){
int iiiiii = 100;
return "hello";
}
}
这个程序较AAA复杂得多,37-1项constant_pool table条目。常量池表的index-tag-解释
1、CONSTANT_Methodref (10)这总是第一个条目。共5u
2、CONSTANT_Double (6).表示它占用2个#以组成一个double常量5.2,共9u
4、CONSTANT_Fieldref (9),由#8和#31描述本成员变量即Yqj,dooD,共5u
5、CONSTANT_String (8).其string_index指向CONSTANT_Utf8_info 结构#32,那是它将被初始化的值。3u
6、CONSTANT_Fieldref (9),由#8和#33描述本成员变量即Yqj,strLjava/lang/String
7、CONSTANT_Fieldref (9),由#8和#34描述本成员变量即Yqj,iI
8、CONSTANT_Class (7).由#35描述类信息Yqj。3u
9、CONSTANT_Class (7).由#36描述类信息java/lang/String。3u
10-29,CONSTANT_Utf8 (1).各种保存Utf8字符串的结构。分别是:
#10(i),#11(I),#12(doo),#13(D),#14(ConstantValue),
#15(str),#16(Ljava/lang/String),#17(<init>),#18(()V),#19(Code),
#20(LineNumberTable),#21(LocalVariableTable),#22(this),#23(Lyqj),
#24(foo),#25(()Ljava/lang/Object),#26(iiiiii),#27(<clinit>),
#28(SourceFile),#29(Yqj.java),
30、CONSTANT_NameAndType (12).由#17,#18说明的信息,<init>和()V
31、CONSTANT_NameAndType (12).由#12,#13说明的信息,<doo>和D
32、CONSTANT_Utf8 (1).hello
33、CONSTANT_NameAndType (12).由#15,#16说明的信息,str和Ljava/lang/String
34、CONSTANT_NameAndType (12).由#10,#11说明的信息,i和I
35、CONSTANT_Utf8 (1).Yqj
36、CONSTANT_Utf8 (1).java/lang/String
除了JVM中预定义的字符串(java/lang/String、<init>、()V、I、SourceFile等等)、表示成员的标识符(LYqj、i、doo、iiiiii、foo),程序中定义的命名常量的值5.2CONSTANT_Double,字符串常量#32的CONSTANT_Utf8 被列入constant_pool table。
Note: LocalVariableTable is not a necessary attribute. Some compilers even do not generate a LocalVariableTable in .class files, e.g. the jdk 1.4.2_11.