2

私は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        
}

これですべて意味がわかり、さまざまなバイトコードを理解できましたが、頭に浮かんだ質問は次のとおりです。

  • 「m1」と「m2」がinvokestatic呼び出しで言及されているので、何らかの方法で呼び出されますが、javap呼び出しで実際のバイトコード出力が表示されません!
  • さて、それらはインライン化されていますか、それとも表示されませんか? もしそうなら、なぜですか?

繰り返しますが、この質問は、javac が内部でこのような処理をどのように処理するかという純粋な関心事です。ありがとう!

4

2 に答える 2

1

Javac はメソッドのインライン化を一切行いません。実行時のこの最適化やその他の最適化は JVM に任せます。JVM (少なくとも Oracle のもの) はインライン化が非常に得意で、複数のレベルにインライン化されます。実行時にモノモーフィックであることが判明した場合、いくつかのポリモーフィック メソッド呼び出しをインライン化することもできます (つまり、特定の呼び出しサイトで、メソッドがオーバーライド可能であるにもかかわらず、呼び出される可能性のあるメソッド実装が 1 つしかない場合を検出しようとします)。

ProGuardなどのポストプロセッサを使用して、コンパイル後に Java コードをインライン化および最適化することもできます。

PS 次のような新しい String オブジェクトを作成します。

return new String("foobar");

無駄であり、常に不必要です。あなたは簡単に行うことができます:

return "foobar";
于 2013-11-13T09:40:01.357 に答える