TA的每日心情 | 开心 2021-3-12 23:18 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
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反汇编在类中遇到的字节代码。
运行方式如下: C:java>javac JavapTip.java C:java>javap -c -private JavapTip
此命令的输出为:
- Compiled from "JavapTip.java"
- public class JavapTip {
- public JavapTip();
- Code:
- 0: aload_0
- 1: invokespecial #1 // Method java/lang/Object."< init>":()V
- 4: return
- public static void main(java.lang.String[]);
- Code:
- 0: return
- private static java.lang.String withStrings(int);
- Code:
- 0: ldc #2 // String
- 2: astore_1
- 3: iconst_0
- 4: istore_2
- 5: iload_2
- 6: iload_0
- 7: if_icmpge 35
- 10: new #3 // class java/lang/StringBuilder
- 13: dup
- 14: invokespecial #4 // Method java/lang/StringBuilder."< init>":()V
- 17: aload_1
- 18: invokevirtual #5
- // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
- 21: iload_2
- 22: invokevirtual #6 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
- 25: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
- 28: astore_1
- 29: iinc 2, 1
- 32: goto 5
- 35: aload_1
- 36: areturn
- private static java.lang.String withStringBuffer(int);
- Code:
- 0: new #8 // class java/lang/StringBuffer
- 3: dup
- 4: invokespecial #9 // Method java/lang/StringBuffer."< init>":()V
- 7: astore_1
- 8: iconst_0
- 9: istore_2
- 10: iload_2
- 11: iload_0
- 12: if_icmpge 27
- 15: aload_1
- 16: iload_2
- 17: invokevirtual #10 // Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;
- 20: pop
- 21: iinc 2, 1
- 24: goto 10
- 27: aload_1
- 28: invokevirtual #11 // Method java/lang/StringBuffer.toString:()Ljava/lang/String;
- 31: areturn
- }
复制代码 如果你以前没有看过 Java 汇编器,那么这个输出对你来说就会比较难懂,但是你应该可以看到 withString 方法在每次循环的时候都新创建了一个 StringBuilder 实例。然后它将已有的 String 的当前值追加到 StringBuilder 上,然后追加循环的当前值。最后,它对 StringBuilder 调用 toString 并将结果赋给现有的 String 引用。 withStringBuffer 方法与这个方法正好相反,在每次循环的时候 withStringBuffer 只调用现有 StringBuffer 的 append 方法,没有创建新的对象,也没有新的 String 引用。 在这种情况下,我们已经知道了使用 StringBuffer 代替 String 是一种好的做法,但是如果我们不知道呢?那么 javap 可以帮助我们找到答案。 你并不会经常需要一个 Java 反汇编器,但是当你需要的时候,知道你自己的机器已经有一个并且用法相当简单的反汇编器当然是一件好事。如果你感兴趣,看书看看 javap 的其它选项――或许你会发现在你的环境中需要的特性。
|
|