Jvm javac也内联吗?

Jvm javac也内联吗?,jvm,bytecode,javap,Jvm,Bytecode,Javap,我在玩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 Stri

我在玩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
从“Main.java”编译
公共班机{
公用干管();
代码:
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:返回
publicstaticvoidmain(java.lang.String[])抛出java.lang.Exception;
代码:
0:getstatic#2//Field java/lang/System.out:Ljava/io/PrintStream;
3:invokestatic#3//方法m1:()Ljava/lang/String;
6:invokevirtual#4//方法java/io/PrintStream.println:(Ljava/lang/String;)V
9:getstatic#2//Field java/lang/System.out:Ljava/io/PrintStream;
12:invokestatic#5//方法m2:()Ljava/lang/String;
15:invokevirtual#4//方法java/io/PrintStream.println:(Ljava/lang/String;)V
18:返回
}
所有这些都是有道理的,我理解不同的字节码,但我想到的问题是:

  • 我在invokestatic调用中看到了“m1”和“m2”,因此它们被以某种方式调用,但我在javap调用中没有看到它们的实际字节码输出
  • 现在,它们是内联的还是不显示?如果是,为什么

同样,这个问题纯粹是javac如何在内部处理这些东西的问题。谢谢

它们在那里,但是您使用的默认标志不会显示它们,因为它们是私有方法。为了查看m1和m2的定义,请使用

javap -p -c .\Main.class
这将显示所有内部成员,包括private和public。这是您将得到的,如果您使用上述命令

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       
}
PS C:\Users\jbuddha>javap-p-C。\Main.class
从“Main.java”编译
公共班机{
公用干管();
代码:
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:返回
publicstaticvoidmain(java.lang.String[])抛出java.lang.Exception;
代码:
0:getstatic#2//Field java/lang/System.out:Ljava/io/PrintStream;
3:invokestatic#3//方法m1:()Ljava/lang/String;
6:invokevirtual#4//方法java/io/PrintStream.println:(Ljava/lang/String;)V
9:getstatic#2//Field java/lang/System.out:Ljava/io/PrintStream;
12:invokestatic#5//方法m2:()Ljava/lang/String;
15:invokevirtual#4//方法java/io/PrintStream.println:(Ljava/lang/String;)V
18:返回
私有静态java.lang.String m1();
代码:
0:new#6//class java/lang/String
3:dup
4:ldc#7//String foobar
6:invokespecial#8//方法java/lang/String.“:(Ljava/lang/String;)V
9:轮到你了
私有静态java.lang.String m2();
代码:
0:ldc#7//String foobar
2:astore_0
3:new#6//class java/lang/String
6:dup
7:aload_0
8:invokespecial#8//方法java/lang/String.“:(Ljava/lang/String;)V
11:轮到你了
}

Javac没有任何方法内联。它让JVM在运行时负责此优化和其他优化。JVM(至少是Oracle JVM)非常擅长内联,可以内联到多个级别。如果在运行时发现一些多态方法调用是单态的,它甚至可以内联这些多态方法调用(即,在特定的调用站点,它尝试检测何时只有一个可能的方法实现可以被调用,即使该方法是可重写的)

您还可以使用后处理器,如内联和优化编译后的Java代码

注意:创建新的字符串对象,如下所示:

return new String("foobar");
这是浪费,而且总是不必要的。您可以简单地执行以下操作:

return "foobar";

啊,谢谢,私人和p是丢失的链接,非常感谢!嗨,是的,这是我打这个之前的知识,所以我想验证它。私有标志是丢失的链接:)
return "foobar";