龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > JAVA开发 >

用Javap反编译帮你理解Java特性[组图]

时间:2009-12-23 15:42来源:未知 作者:admin 点击:
分享到:
Java 开发人员熟悉在一个循环中使用StringBuffer 来代替串联 String 对象能获得最佳性能。然而,多数开发人员从来没有比较两种方法产生的字节代码的区别。在 Java 开发工具包(JDK)中有

  Java 开发人员熟悉在一个循环中使用StringBuffer 来代替串联 String 对象能获得最佳性能。然而,多数开发人员从来没有比较两种方法产生的字节代码的区别。在 Java 开发工具包(JDK)中有一个叫做 javap 的工具可以告诉你为什么这样做可以获得最佳性能。
     
   <!-- frame contents -->
<!-- /frame contents -->   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();
     }
     }

     现在让我们看看对这个类使用?Cc 选项运行 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 引用。
  
精彩图集

赞助商链接