JVM初学二
Class文件的结构其实也很简单,主要可通过下面的数据结构表示
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]; }
每个java源代码都会生成对应的class文件,文件中最重要的当属constant_pool了,不过首先还是说一下描述符。
A 描述符
Java源代码中有方法、类、域(即成员变量或类变量)几种,这些在Class文件中都有对应的描述符进行描述。例如:
Object method(int i,double d,Thread t)
对应的描述符为:
(IDLjava/lang/Thread;)LJava/Object
格式为(参数描述符*)返回描述符,可以看到函数名称在其中并没有出现。
B 常量池
有了描述符就可以在常量池中对它进行索引了。例如在常量池中包含一种数据结构:
CONSTANT_NameAndType_info { u1 tag; u2 name_index; u2 descriptor_index; }
用于描述域和方法的
其中descriptor_index会索引到一个Constant_Utf8的字符串,这个字符串可能就是前面所说的"(IDLjava/lang/Thread;)LJava/Object"
其中name_index会索引到一个Constant_Utf8的字符串,它是这个方法或域的不完整限定名。(Thread类的完整限定名是 java.lang.Thread, 不完整限定名是Thread)
C 属性
一些的关注还需要放在attributes上,因为这个数据结构中包含了将要被执行的JVM指令代码,attributes的数据结构如下:
attribute_info { u2 attribute_name_index; u4 attribute_length; u1 info[attribute_length]; }
这只是一个可变的结构,对于code来说,它能演化为:
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]; }
我们关心的code就放在code的数组中,另外我们看到了一些关于exception的信息,还有最后居然还又嵌入了attributes信息,这些信息可能是LineNumberTable或LocalVariableTable ,这些都是我们可能想知道的一些调试信息,需要在编译时加上"-g"选项。
知道了Class文件的格式就可以使用JVM加载它,并进行校验,准备和解析了,并加载运行指令