我正在玩javap和一些非常简单的代码,并提出了一个 - 希望很简单 - 的问题。
首先是代码:
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(m1());
System.out.println(m2());
}
private static String m1() {
return new String("foobar");
}
private static String m2() {
String str = "foobar";
return new String(str);
}
}
现在我编译了代码并查看了输出(现在省略-verbose)。
$ javap -c Main.class
Compiled from "Main.java"
public class Main {
public Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: invokestatic #3 // Method m1:()Ljava/lang/String;
6: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
9: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
12: invokestatic #5 // Method m2:()Ljava/lang/String;
15: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
18: return
}
现在所有这些都有意义,我理解不同的字节代码,但我想到的问题是:
同样,这个问题只是javac内部处理这些东西的纯粹兴趣。谢谢!
答案 0 :(得分:6)
它们在那里,但您使用的默认标志不会显示它们,因为它们是私有方法。为了看到m1和amp;的定义。 m2也是,使用
javap -p -c .\Main.class
这将显示所有内部成员,包括私人和公共成员。如果您使用上述命令,这将是您将获得的。
PS C:\Users\jbuddha> javap -p -c .\Main.class
Compiled from "Main.java"
public class Main {
public Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: invokestatic #3 // Method m1:()Ljava/lang/String;
6: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
9: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
12: invokestatic #5 // Method m2:()Ljava/lang/String;
15: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
18: return
private static java.lang.String m1();
Code:
0: new #6 // class java/lang/String
3: dup
4: ldc #7 // String foobar
6: invokespecial #8 // Method java/lang/String."<init>":(Ljava/lang/String;)V
9: areturn
private static java.lang.String m2();
Code:
0: ldc #7 // String foobar
2: astore_0
3: new #6 // class java/lang/String
6: dup
7: aload_0
8: invokespecial #8 // Method java/lang/String."<init>":(Ljava/lang/String;)V
11: areturn
}
答案 1 :(得分:1)
Javac没有任何内联方法。它使JVM在运行时负责此优化和其他优化。 JVM(至少是Oracle)非常擅长内联,并将内联到多个级别。如果在运行时发现它们是单态的,它甚至可以内联一些多态方法调用(即,在特定的调用站点,它会尝试检测何时只有一个可能的方法实现,即使该方法可被覆盖也可以调用)。
您还可以使用像ProGuard这样的后处理器在编译后内联和优化Java代码。
P.S。像这样创建新的String对象:
return new String("foobar");
浪费并且总是不必要的。你可以这样做:
return "foobar";