Есть ли встроенный javac?

Я играл с 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 обрабатывает этот материал внутри. Спасибо!


person daschl    schedule 13.11.2013    source источник


Ответы (2)


Они есть, но используемые вами флаги по умолчанию не отображают их, поскольку они являются приватными методами. Чтобы увидеть определение как для m1, так и для 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       
}
person Buddha    schedule 13.11.2013
comment
ах, спасибо, частный и -p был недостающим звеном Большое спасибо! - person daschl; 13.11.2013

Javac вообще не встраивает методы. За эту и другую оптимизацию во время выполнения отвечает JVM. JVM (по крайней мере, Oracle) очень хороша для встраивания и будет встраиваться на несколько уровней. Он может даже встраивать вызовы некоторых полиморфных методов, если они оказываются мономорфными во время выполнения (т. е. в конкретном месте вызова он пытается определить, когда существует только одна возможная реализация метода, который может быть вызван, даже если этот метод можно переопределить).

Вы также можете использовать постпроцессор, такой как ProGuard, для встраивания и оптимизации кода Java после компиляции.

P.S. создание новых объектов String следующим образом:

return new String("foobar");

расточительно и всегда ненужно. Вы можете просто сделать:

return "foobar";
person Boann    schedule 13.11.2013
comment
Привет, да, это были мои знания до того, как я наткнулся на это, поэтому я хотел проверить это. Частный флаг был недостающим звеном, по-видимому :) - person daschl; 13.11.2013