从基本结构到Java 7新特性(5)

发表于:2013-01-05来源:ImportNew作者:朱伟杰点击数: 标签:java
上面的内容是来自《The Java Virtual Machine Specification,Second Edition》的4.1节The ClassFile Structure。 之前反汇编的UserService.class文件反汇编的结果的前16个字节在十六

  上面的内容是来自《The Java Virtual Machine Specification,Second Edition》的4.1节“The ClassFile Structure"。

  之前反汇编的UserService.class文件反汇编的结果的前16个字节在十六进制编辑器中如下所示:

  ca fe ba be 00 00 00 32 00 28 07 00 02 01 00 1b

  通过这些数值,我们可以来看看class文件的格式。

  magic:class文件最开始的四个字节是魔数。它的值是用来标识Java class文件的。从上面的内容里可以看出,魔数 的值是0xCAFEBABE。简而言之,只有一个文件的起始4字节是0xCAFEBABE的时候,它才会被当作Java class文件来处理。

  minor_version,major_version:接下来的四个字节表示的是class文件的版本。UserService.class文件里的是0x00000032,所以这个class文件的版本是50.0。JDK 1.6编译的class文件的版本是50.0,JDK 1.5编译出来的class文件的版本是49.0。JVM必须对低版本的class文件保持后向兼容性,也就是低版本的class文件可以运行在高版本的JVM上。不过,反过来就不行了,当一个高版本的class文件运行在低版本的JVM上时,会出现java.lang.UnsupportedClassVersionError的错误。

  constant_pool_count,constant_pool[]:在版本号之后,存放的是类的常量池。这里保存的信息将会放入运行时常量池(Runtime Constant Pool)中去,这个后面会讲解的。在加载一个class文件的时候,JVM会把常量池里的信息存放在方法区的运行时常量区里。UserService.class文件里的constant_pool_count的值是0x0028,这表示常量池里有39(40-1)个常量。

  access_flags:这是表示一个类的描述符的标志;换句话说,它表示一个类是public,final还是abstract以及是不是接口的标志。

  fields_count,fields[]:当前类的成员变量的数量以及成员变量的信息。成员变量的信息包含变量名,类型,修饰符以及变量在constant_pool里的索引。

  methods_count,methods[]:当前类的方法数量以及方法的信息。方法的信息包含方法名,参数的数量和类型,返回值的类型,修饰符,以及方法在constant_pool里的索引,方法的可执行代码以及异常信息。

  attributes_count,attributes[]:attribution_info结构包含不同种类的属性。field_info和method_info里都包含了attribute_info结构。

  javap简要地给出了class文件的一个可读形式。当你用"java -verbose"命令来分析UserService.class时,会输出如下的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Compiled from "UserService.java"
 
public class com.nhn.service.UserService extends java.lang.Object
  SourceFile: "UserService.java"
  minor version: 0
  major version: 50
  Constant pool:const #1 = class        #2;     //  com/nhn/service/UserService
const #2 = Asciz        com/nhn/service/UserService;
const #3 = class        #4;     //  java/lang/Object
const #4 = Asciz        java/lang/Object;
const #5 = Asciz        admin;
const #6 = Asciz        Lcom/nhn/user/UserAdmin;;// … omitted - constant pool continued …
 
{
// … omitted - method information …
 
public void add(java.lang.String);
  Code:
   Stack=2, Locals=2, Args_size=2
   0:   aload_0
   1:   getfield        #15; //Field admin:Lcom/nhn/user/UserAdmin;
   4:   aload_1
   5:   invokevirtual   #23; //Method com/nhn/user/UserAdmin.addUser:(Ljava/lang/String;)Lcom/nhn/user/User;
   8:   pop
   9:   return  LineNumberTable:
   line 14: 0
   line 15: 9  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      10      0    this       Lcom/nhn/service/UserService;
   0      10      1    userName       Ljava/lang/String; // … Omitted - Other method information …
}

原文转自:http://www.ltesting.net