[公告] 问一个javap查看字节码的问题
michael9527
2012-04-19
使用javap查看字节码发现一个奇怪的问题,
在centos(使用的是JDK是 HotSpot 1.6.0_29) 和 windows xp(使用的JDK是 HotSpot 1.6.0_31) centos和windows上javap的结果都是一样的 写了一个测试类,如下: package com.test; public class MyClass implements Runnable { public boolean boolean_value = true; public byte byte_value = 33; public short short_value = 1; public char char_vlaue = 'a'; public int int_value = 234567; public long long_value = 100L; public float float_value = 3.33F; public double double_value = 3.1415; public String ss = "12345"; public static void main(String[] args) { // TODO Auto-generated method stub } public void run() { } public void xx() { Runnable r = this; r.run(); } } javap -verbose MyClass 内容为:(只列出了常量池部分,其余的省略了) F:\>javap -verbose MyClass Compiled from "MyClass.java" public class com.test.MyClass extends java.lang.Object implements java.lang.Runn able SourceFile: "MyClass.java" minor version: 0 major version: 50 Constant pool: const #1 = class #2; // com/test/MyClass const #2 = Asciz com/test/MyClass; const #3 = class #4; // java/lang/Object const #4 = Asciz java/lang/Object; const #5 = class #6; // java/lang/Runnable const #6 = Asciz java/lang/Runnable; const #7 = Asciz boolean_value; const #8 = Asciz Z; const #9 = Asciz byte_value; const #10 = Asciz B; const #11 = Asciz short_value; const #12 = Asciz S; const #13 = Asciz char_vlaue; const #14 = Asciz C; const #15 = Asciz int_value; const #16 = Asciz I; const #17 = Asciz long_value; const #18 = Asciz J; const #19 = Asciz float_value; const #20 = Asciz F; const #21 = Asciz double_value; const #22 = Asciz D; const #23 = Asciz ss; const #24 = Asciz Ljava/lang/String;; const #25 = Asciz <init>; const #26 = Asciz ()V; const #27 = Asciz Code; const #28 = Method #3.#29; // java/lang/Object."<init>":()V const #29 = NameAndType #25:#26;// "<init>":()V const #30 = Field #1.#31; // com/test/MyClass.boolean_value:Z const #31 = NameAndType #7:#8;// boolean_value:Z const #32 = Field #1.#33; // com/test/MyClass.byte_value:B const #33 = NameAndType #9:#10;// byte_value:B const #34 = Field #1.#35; // com/test/MyClass.short_value:S const #35 = NameAndType #11:#12;// short_value:S const #36 = Field #1.#37; // com/test/MyClass.char_vlaue:C const #37 = NameAndType #13:#14;// char_vlaue:C const #38 = int 234567; const #39 = Field #1.#40; // com/test/MyClass.int_value:I const #40 = NameAndType #15:#16;// int_value:I const #41 = long 100l; const #43 = Field #1.#44; // com/test/MyClass.long_value:J const #44 = NameAndType #17:#18;// long_value:J const #45 = float 3.33f; const #46 = Field #1.#47; // com/test/MyClass.float_value:F const #47 = NameAndType #19:#20;// float_value:F const #48 = double 3.1415d; const #50 = Field #1.#51; // com/test/MyClass.double_value:D const #51 = NameAndType #21:#22;// double_value:D const #52 = String #53; // 12345 const #53 = Asciz 12345; const #54 = Field #1.#55; // com/test/MyClass.ss:Ljava/lang/String; const #55 = NameAndType #23:#24;// ss:Ljava/lang/String; const #56 = Asciz LineNumberTable; const #57 = Asciz LocalVariableTable; const #58 = Asciz this; const #59 = Asciz Lcom/test/MyClass;; const #60 = Asciz main; const #61 = Asciz ([Ljava/lang/String;)V; const #62 = Asciz args; const #63 = Asciz [Ljava/lang/String;; const #64 = Asciz run; const #65 = Asciz xx; const #66 = InterfaceMethod #5.#67; // java/lang/Runnable.run:()V const #67 = NameAndType #64:#26;// run:()V const #68 = Asciz r; const #69 = Asciz Ljava/lang/Runnable;; const #70 = Asciz SourceFile; const #71 = Asciz MyClass.java; 注意看这个常量池的下标增长顺序, 没有42,也没有49。 查看Myclass.class,前10个字节是: CA FE BA BE 00 00 00 32 00 48 也就是一共有71一个常量,从下标个数来看是对的,但不明白为何显示的时候少了42和49? 此外还有一问题,从源码中看我定义了这几个变量: public byte byte_value = 33; public short short_value = 1; public char char_vlaue = 'a'; 不过从字节码显示结果看,并没有33,1,'a'这些相关的信息,但如果用一些反编译工具的话,编译后的java和源码结果是可以对应上的,所以不清楚这些信息是存在哪里了?还是说javap就没有显示出来? |
|
RednaxelaFX
2012-04-19
短整型常量是直接嵌在指令里的。
例如 iconst_<n>,n从-1到5 bipush,用来load一个字节宽的整数常量 sipush,用来load两个字节宽的整数常量 在short范围之外的整数常量才会出现在常量池里。 你看到常量池里有些下标缺失,是因为long和double是占两个相邻的项的…这个例子里41和48一个是long一个是double,所以42和49就没了。 |
|
michael9527
2012-04-19
public com.test.MyClass(); Code: Stack=3, Locals=1, Args_size=1 0: aload_0 1: invokespecial #28; //Method java/lang/Object."<init>":()V 4: aload_0 5: iconst_1 6: putfield #30; //Field boolean_value:Z 9: aload_0 10: bipush 33 12: putfield #32; //Field byte_value:B 15: aload_0 16: iconst_1 17: putfield #34; //Field short_value:S 20: aload_0 21: bipush 97 23: putfield #36; //Field char_vlaue:C 呵呵,只关注常量池,没想到内嵌到指令里了,另外发现如果变量定义为final的,也会出现在常量池里。多谢R大。 |