java反编译查看字节码

深入理解字节码点击这里 

jdk中的bin里面自带有反编译的程序,叫javap.exe,利用他可以从编译生成的.class查看出对应的字节码代码

具体方法如下:

1.javap -verbose ** >> **.txt

例:

随便写个java类Person

class Person{
	String name;	
	char sex;
	int age;
	Person(){
	}
	Person(String name,char sex,int age){
	this.name=name;
	this.sex=sex;
	this.age=age;	
	}
	String toString(int a){
	return(String.valueOf(a));
	}
	String toString(char a){
	return(String.valueOf(a));
	}
}

编译生成.class后,放到桌面上,shift+右键在当前窗口打开命令行(win7可以,xp不行,就是去.class对应的目录输入命令)输入
javap -verbose Person >> Person.txt
然后在桌面上就看到了Person.txt

内容:

Classfile /C:/Users/linux_v/Desktop/Person.class
  Last modified Oct 11, 2012; size 589 bytes
  MD5 checksum 137de4fcce084d25ffb5c93b1708f63a
  Compiled from "Person.java"
class Person
  SourceFile: "Person.java"
  minor version: 0
  major version: 51
  flags: ACC_SUPER

Constant pool:
   #1 = Methodref          #8.#25         //  java/lang/Object."<init>":()V
   #2 = Fieldref           #7.#26         //  Person.name:Ljava/lang/String;
   #3 = Fieldref           #7.#27         //  Person.sex:C
   #4 = Fieldref           #7.#28         //  Person.age:I
   #5 = Methodref          #29.#30        //  java/lang/String.valueOf:(I)Ljava/lang/String;
   #6 = Methodref          #29.#31        //  java/lang/String.valueOf:(C)Ljava/lang/String;
   #7 = Class              #32            //  Person
   #8 = Class              #33            //  java/lang/Object
   #9 = Utf8               name
  #10 = Utf8               Ljava/lang/String;
  #11 = Utf8               sex
  #12 = Utf8               C
  #13 = Utf8               age
  #14 = Utf8               I
  #15 = Utf8               <init>
  #16 = Utf8               ()V
  #17 = Utf8               Code
  #18 = Utf8               LineNumberTable
  #19 = Utf8               (Ljava/lang/String;CI)V
  #20 = Utf8               toString
  #21 = Utf8               (I)Ljava/lang/String;
  #22 = Utf8               (C)Ljava/lang/String;
  #23 = Utf8               SourceFile
  #24 = Utf8               Person.java
  #25 = NameAndType        #15:#16        //  "<init>":()V
  #26 = NameAndType        #9:#10         //  name:Ljava/lang/String;
  #27 = NameAndType        #11:#12        //  sex:C
  #28 = NameAndType        #13:#14        //  age:I
  #29 = Class              #34            //  java/lang/String
  #30 = NameAndType        #35:#21        //  valueOf:(I)Ljava/lang/String;
  #31 = NameAndType        #35:#22        //  valueOf:(C)Ljava/lang/String;
  #32 = Utf8               Person
  #33 = Utf8               java/lang/Object
  #34 = Utf8               java/lang/String
  #35 = Utf8               valueOf
{
  java.lang.String name;
    flags: 


  char sex;
    flags: 


  int age;
    flags: 


  Person();
    flags: 

    Code:
      stack=1, locals=1, args_size=1
         0: aload_0       
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return        
      LineNumberTable:
        line 5: 0
        line 6: 4

  Person(java.lang.String, char, int);
    flags: 

    Code:
      stack=2, locals=4, args_size=4
         0: aload_0       
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0       
         5: aload_1       
         6: putfield      #2                  // Field name:Ljava/lang/String;
         9: aload_0       
        10: iload_2       
        11: putfield      #3                  // Field sex:C
        14: aload_0       
        15: iload_3       
        16: putfield      #4                  // Field age:I
        19: return        
      LineNumberTable:
        line 7: 0
        line 8: 4
        line 9: 9
        line 10: 14
        line 11: 19

  java.lang.String toString(int);
    flags: 

    Code:
      stack=1, locals=2, args_size=2
         0: iload_1       
         1: invokestatic  #5                  // Method java/lang/String.valueOf:(I)Ljava/lang/String;
         4: areturn       
      LineNumberTable:
        line 13: 0

  java.lang.String toString(char);
    flags: 

    Code:
      stack=1, locals=2, args_size=2
         0: iload_1       
         1: invokestatic  #6                  // Method java/lang/String.valueOf:(C)Ljava/lang/String;
         4: areturn       
      LineNumberTable:
        line 16: 0
}
看着挺高端的,有时间再慢慢研究,还有另一种命令

2.javap –c ** >> **.txt

上面链接给的测试类,我们确实时常讨论String,StringBuilder,StringBuffer之间的区别,其实看字节码确实能看出一点区别,即使不懂字节码。

TestString.java

public class TestString { 
    public String testString(String str1, String str2){ 
       return str1 + str2; 
    } 
    public String testStringBuffer(StringBuffer sb, String str){ 
       return sb.append(str).toString(); 
    }
    public String testStringBuilder(StringBuilder sb, String str){
	return sb.append(str).toString();
    } 
} 
编译生成字节码后,输入
javap -c TestString >> TestString.txt
生成文本如下:

Compiled from "TestString.java"
public class TestString {
  public TestString();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public java.lang.String testString(java.lang.String, java.lang.String);
    Code:
       0: new           #2                  // class java/lang/StringBuilder
       3: dup           
       4: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
       7: aload_1       
       8: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      11: aload_2       
      12: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      15: invokevirtual #5                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      18: areturn       

  public java.lang.String testStringBuffer(java.lang.StringBuffer, java.lang.String);
    Code:
       0: aload_1       
       1: aload_2       
       2: invokevirtual #6                  // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
       5: invokevirtual #7                  // Method java/lang/StringBuffer.toString:()Ljava/lang/String;
       8: areturn       
}
Compiled from "TestString.java"
public class TestString {
  public TestString();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public java.lang.String testString(java.lang.String, java.lang.String);
    Code:
       0: new           #2                  // class java/lang/StringBuilder
       3: dup           
       4: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
       7: aload_1       
       8: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      11: aload_2       
      12: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      15: invokevirtual #5                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      18: areturn       

  public java.lang.String testStringBuffer(java.lang.StringBuffer, java.lang.String);
    Code:
       0: aload_1       
       1: aload_2       
       2: invokevirtual #6                  // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
       5: invokevirtual #7                  // Method java/lang/StringBuffer.toString:()Ljava/lang/String;
       8: areturn       

  public java.lang.String testStringBuilder(java.lang.StringBuilder, java.lang.String);
    Code:
       0: aload_1       
       1: aload_2       
       2: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       5: invokevirtual #5                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
       8: areturn       
}

可以看到对于定义String类型的字符做字符连接时所执行的方法要多于StringBuffer和StringBuilder,StringBuffer和StringBuilder是一样的,不过StringBuilder是非线程安全的,StringBuffer是线程安全的,所以一般推荐使用StringBuffer,以前看人用java代码测试运行时间来观察执行效率,其实这样通过字节码大体猜测感觉也是挺不错的。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值