Java类反汇编命令

 可能大家平时用编译命令javac和解释命令java用得比较多,Java类反汇编程序的命令javap用得比较少。我们在命令行窗口先用javap -help看下javap工具支持的选项:

D:/test>javap -help
Usage: javap <options> <classes>...

where options include:
    -c                         Disassemble the code
    -classpath <pathlist>      Specify where to find user class files
    -extdirs <dirs>            Override location of installed extensions
    -help                      Print this usage message
    -J<flag>                   Pass <flag> directly to the runtime system
    -l                         Print line number and local variable tables
    -public                    Show only public classes and members
    -protected                 Show protected/public classes and members
    -package                   Show package/protected/public classes and members (default)
    -private                   Show all classes and members
    -s                         Print internal type signatures
    -bootclasspath <pathlist> Override location of class files loaded by the bootstrap class loader
    -verbose                   Print stack size, number of locals and args for methods   If verifying, print reasons for failure

        我平时一般用c选项用得比较多,该命令用于列出每个方法所执行的JVM指令,并显示每个方法的字节码的实际作用。

        我们写个HelloWorld的程序来测试一下该命令。

public class HelloWorld {
public static void main(String[] args){
   System.out.println("Hello World!");
}
}

        然后在命令行将其编译,生成HelloWorld.class文件。

        接着我们输入javap -c HelloWorld >> disa.txt

“>> disa.txt”意思是重定向输出流,将所生成的信息输出到disa.txt文本文件中。其内容如下:


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

public static void main(java.lang.String[]);
   Code:
    0:    getstatic        #2; //Field java/lang/System.out:Ljava/io/PrintStream;
    3:    ldc      #3; //String Hello World!
    5:    invokevirtual    #4; //Method java/io/PrintStream.println:(Ljava/lang/Str
ing;)V
    8:    return

}

        我们对main方法下面几行进行解释:

        这几行用于转换Java语言中的代码行System.out.println("Hello World!");

        第一个指令getstatic从java.lang.system对象的out字段中检索PrintStream对象,并放到操作数栈中。第二行的ldc 将字符串"Hello World!"压到操作数栈中。最后,invokevirtual执行java.io.PrintStream类中的println方法。该方法的正确执 行要求操作数栈中存在一个String以及java.io.PrintStream类的一个实例,并依次排列。
---------------------------------------------------------------------------------------------------------------
用javap 反汇编帮你理解java特性 (使用 javap 深入查看类文件)
  作者: Builder.com
  使用 javap 深入查看类文件
   Java 开发人员熟悉在一个循环中使用StringBuffer 来代替串联 String 对象能获得最佳性能。然而,多数开发人员从来没有比较两种方法产生的字节代码的区别。在 Java 开发工具包(JDK)中有一个叫做 javap 的工具可以告诉你为什么这样做可以获得最佳性能。
  Javap 将一个类和它的方法的一些转储信息输出到标准输出。该工具不把代码反编译为 java 源代码,但是它会把字节代码反汇编成为由 Java 虚拟机规范定义的字节代码指令。
  在你需要查看编译器为你或者给你做了什么的时候,或者你想要看一处代码的改动对编译后的类文件有什么影响的时候,javap 相当有用。
   现在以我们前面提到的 StringBuffer 和 String 作为一个例子。下面是一个专门为例子设计的类,它有两个方法,都返回一个由0到 n 的数字组成的 String,其中 n 由调用者提供。两个方法唯一的区别在于一个使用 String 构建结果,另外一个使用 StringBuffer 构建结果。
  public class JavapTip {
   public static void main(String []args) {
   }
   private static String withStrings(int count) {
   String s = "";
   for (int i = 0; i < count; i++) {
   s += i;
   }
   return s;
   }
   private static String withStringBuffer(int count) {
   StringBuffer sb = new StringBuffer();
   for (int i = 0; i < count; i++) {
   sb.append(i);
   }
   return sb.toString();
   }
  }
  现在让我们看看对这个类使用–c 选项运行 javap 的输出。-c 选项告诉 javap 反汇编在类中遇到的字节代码。
  运行方式如下:
  >javap -c JavapTip
  此命令的输出为:
  Method java.lang.String withStrings(int)
   0 ldc #2
   2 astore_1
   3 iconst_0
   4 istore_2
   5 goto 30
   8 new #3
   11 dup
   12 invokespecial #4
   15 aload_1
   16 invokevirtual #5
   19 iload_2
   20 invokevirtual #6
   23 invokevirtual #7
   26 astore_1
   27 iinc 2 1
   30 iload_2
   31 iload_0
   32 if_icmplt 8
   35 aload_1
   36 areturn
  Method java.lang.String withStringBuffer(int)
   0 new #3
   3 dup
   4 invokespecial #4
   7 astore_1
   8 iconst_0
   9 istore_2
   10 goto 22
   13 aload_1
   14 iload_2
   15 invokevirtual #6
   18 pop
   19 iinc 2 1
   22 iload_2
   23 iload_0
   24 if_icmplt 13
   27 aload_1
   28 invokevirtual #7
   31 areturn
   如果你以前没有看过 Java 汇编器,那么这个输出对你来说就会比较难懂,但是你应该可以看到 withString 方法在每次循环的时候都新创建了一个 StringBuffer 实例。然后它将已有的 String 的当前值追加到 StringBuffer 上,然后追加循环的当前值。最后,它对 buffer 调用 toString 并将结果赋给现有的 String 引用。
  withStringBuffer 方法与这个方法正好相反,在每次循环的时候 withStringBuffer 只调用现有 StringBuffer 的 append 方法,没有创建新的对象,也没有新的 String 引用。
  在这种情况下,我们已经知道了使用 StringBuffer 代替 String 是一种好的做法,但是如果我们不知道呢?那么 javap 可以帮助我们找到答案。 在这里你可以看到更详细的关于String,StringBuffer 的解释
  你并不会经常需要一个 Java 反汇编器,但是当你需要的时候,知道你自己的机器已经有一个并且用法相当简单的反汇编器当然是一件好事。如果你感兴趣,看书看看 javap 的其它选项——或许你会发现在你的环境中需要的特性。
  --------------------------------------------------------------------------------
  本文作者:David Petersheim是Genscape公司的一位应用开发主任。他设计和开发服务器端应用程序来获取和处理实时能源数据。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值