具体的实例
Java文件
package com.weixuan.test; public class MyTest { private int age; private String name; public int getAge() { return age; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public void setName(String name) { this.name = name; } public static void main(String[] args) { } }
使用javac -g:vars MyTest.java编译,显示localvariable
C:\Users\weixu_000\Desktop>javac -g:vars MyTest.java C:\Users\weixu_000\Desktop>javap -verbose MyTest.class Classfile /C:/Users/weixu_000/Desktop/MyTest.class Last modified 2015-7-5; size 708 bytes MD5 checksum 2d2527c48aba8637fbf99840391879aa public class com.weixuan.test.MyTest minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #5.#28 // java/lang/Object."<init>":()V #2 = Fieldref #4.#29 // com/weixuan/test/MyTest.age:I #3 = Fieldref #4.#30 // com/weixuan/test/MyTest.name:Ljava/ lang/String; #4 = Class #31 // com/weixuan/test/MyTest #5 = Class #32 // java/lang/Object #6 = Utf8 age #7 = Utf8 I #8 = Utf8 name #9 = Utf8 Ljava/lang/String; #10 = Utf8 <init> #11 = Utf8 ()V #12 = Utf8 Code #13 = Utf8 LocalVariableTable #14 = Utf8 this #15 = Utf8 Lcom/weixuan/test/MyTest; #16 = Utf8 getAge #17 = Utf8 ()I #18 = Utf8 getName #19 = Utf8 ()Ljava/lang/String; #20 = Utf8 setAge #21 = Utf8 (I)V #22 = Utf8 setName #23 = Utf8 (Ljava/lang/String;)V #24 = Utf8 main #25 = Utf8 ([Ljava/lang/String;)V #26 = Utf8 args #27 = Utf8 [Ljava/lang/String; #28 = NameAndType #10:#11 // "<init>":()V #29 = NameAndType #6:#7 // age:I #30 = NameAndType #8:#9 // name:Ljava/lang/String; #31 = Utf8 com/weixuan/test/MyTest #32 = Utf8 java/lang/Object { public com.weixuan.test.MyTest(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init> ":()V 4: return LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/weixuan/test/MyTest; public int getAge(); descriptor: ()I flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #2 // Field age:I 4: ireturn LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/weixuan/test/MyTest; public java.lang.String getName(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #3 // Field name:Ljava/lang/String; 4: areturn LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/weixuan/test/MyTest; public void setAge(int); descriptor: (I)V flags: ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: aload_0 1: iload_1 2: putfield #2 // Field age:I 5: return LocalVariableTable: Start Length Slot Name Signature 0 6 0 this Lcom/weixuan/test/MyTest; 0 6 1 age I public void setName(java.lang.String); descriptor: (Ljava/lang/String;)V flags: ACC_PUBLIC Code: stack=2, locals=2, args_size=2 0: aload_0 1: aload_1 2: putfield #3 // Field name:Ljava/lang/String; 5: return LocalVariableTable: Start Length Slot Name Signature 0 6 0 this Lcom/weixuan/test/MyTest; 0 6 1 name Ljava/lang/String; public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=0, locals=1, args_size=1 0: return LocalVariableTable: Start Length Slot Name Signature 0 1 0 args [Ljava/lang/String; }
对应的字节码
cafe babe 0000 0034 001f 0a00 0500 1a09 0004 001b 0900 0400 1c07 001d 0700 1e01 0003 6167 6501 0001 4901 0004 6e61 6d65 0100 124c 6a61 7661 2f6c 616e 672f 5374 7269 6e67 3b01 0006 3c69 6e69 743e 0100 0328 2956 0100 0443 6f64 6501 000f 4c69 6e65 4e75 6d62 6572 5461 626c 6501 0006 6765 7441 6765 0100 0328 2949 0100 0767 6574 4e61 6d65 0100 1428 294c 6a61 7661 2f6c 616e 672f 5374 7269 6e67 3b01 0006 7365 7441 6765 0100 0428 4929 5601 0007 7365 744e 616d 6501 0015 284c 6a61 7661 2f6c 616e 672f 5374 7269 6e67 3b29 5601 0004 6d61 696e 0100 1628 5b4c 6a61 7661 2f6c 616e 672f 5374 7269 6e67 3b29 5601 000a 536f 7572 6365 4669 6c65 0100 0b4d 7954 6573 742e 6a61 7661 0c00 0a00 0b0c 0006 0007 0c00 0800 0901 0017 636f 6d2f 7765 6978 7561 6e2f 7465 7374 2f4d 7954 6573 7401 0010 6a61 7661 2f6c 616e 672f 4f62 6a65 6374 0021 0004 0005 0000 0002 0002 0006 0007 0000 0002 0008 0009 0000 0006 0001 000a 000b 0001 000c 0000 001d 0001 0001 0000 0005 2ab7 0001 b100 0000 0100 0d00 0000 0600 0100 0000 0300 0100 0e00 0f00 0100 0c00 0000 1d00 0100 0100 0000 052a b400 02ac 0000 0001 000d 0000 0006 0001 0000 0009 0001 0010 0011 0001 000c 0000 001d 0001 0001 0000 0005 2ab4 0003 b000 0000 0100 0d00 0000 0600 0100 0000 0d00 0100 1200 1300 0100 0c00 0000 2200 0200 0200 0000 062a 1bb5 0002 b100 0000 0100 0d00 0000 0a00 0200 0000 1100 0500 1200 0100 1400 1500 0100 0c00 0000 2200 0200 0200 0000 062a 2bb5 0003 b100 0000 0100 0d00 0000 0a00 0200 0000 1500 0500 1600 0900 1600 1700 0100 0c00 0000 1900 0000 0100 0000 01b1 0000 0001 000d 0000 0006 0001 0000 001a 0001 0018 0000 0002 0019
具体的解释
1、magic number : 前四个字节 cafe babe,咖啡宝贝
2、次主版本:接下来的四个字节 0000 0034
3、常量池
前两个字节是常量池容量计数器,后面才是常量池
001f : 常量池容量计数器 十进制的31 也就是说,有30个常量,索引是1到30
4、访问标志
常量池结束之后,就是访问标志。
0021 : 只有ACC_PUBLIC和ACC_SUPER为真。即这个类是public 的普通类,无其他修饰符
5、类索引,父类索引与接口索引集合
访问标志之后,就是类索引,父类索引和接口索引集合。
0004 0005 0000 0004:类索引是4,查表, #4 = Class #29 // com/weixuan/test/MyTest index是29,#29 = Utf8 com/weixuan/test/MyTest 全类名 0005:父类索引是5,查表, #5 = Class #30 // java/lang/Object index是30,#30 = Utf8 java/lang/Object 父类是Object 0000:接口信息为0,无接口信息。
6、字段表集合
0002 0002 0006 0007 0000 0002 0008 0009 0000
接口索引集合之后就是字段表的两个字节的字段容量计数器
0002: 2个属性。 在源代码中是,age和name,我们验证一下:
0002 0002 0006 0007
0002:访问标志,查字段访问标志表,0002--->0x0002--->ACC_PRIVATE
0006:name_index,值是6,查表,第一个属性是age
#6 = Utf8 age
0007:第一个属性的描述符索引,值是7,查表,属性类型是I--->int
#7 = Utf8 I
0000:属性信息,无
0002:第二个属性的访问标志,ACC_PRIVATE
0008:name_index,值是8,查表,第二个属性是name
#8 = Utf8 name
0009:描述符索引 值为9,查表,L对象类型,即string 对象类型
#9 = Utf8 Ljava/lang/String;
0000:属性信息,无
7、方法表集合
字段表结束就是方法表集合开头的方法容量计数器,然后是方法表的内容0006 0001 000a 000b 0001 000c
0006:methods_count 6个方法
源代码中分别是getName(),getAge(),setName(),setAge(),main(),以及编译器添加的<init>方法
0001:访问标志 0001 ---> ACC_PUBLIC,public
000a:name_index,值为10,查表
#10 = Utf8 <init>
000b:描述符索引,11,查表,方法是 public void()类型,无参
#11 = Utf8 ()V
0001:属性数量 1个
000c:属性索引 值是12 查表,对应的常量是code
#12 = Utf8 Code
8、 编译时,javac -g:vars MyTest.java,可以显示localvariable
分析一下<init>方法的code属性public com.weixuan.test.MyTest();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>
":()V
4: return
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/weixuan/test/MyTest;
可以看到,statck:1,local:1,codelength:5
找到相应的字节码
0001 0001 0000 0005 2ab7 0001 b1
0001 0001 0000 0005 对应的是stack,local,codelength
2ab7 0001 b1是code的内容