2013-11-13 5 views
2

Я играл с джавапом и очень простым кодом, и это подняло вопрос - надеюсь, простой.Является ли javac также встроенным?

здесь код первого:

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

ответ

6

Они есть, но используемые по умолчанию флаги не показывают их, поскольку они являются частными методами. Для того, чтобы увидеть определение для обоих m1 & м2, а также использовать

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  
} 
+0

ah спасибо, частное и -p было недостающим звеном Спасибо большое! – daschl

1

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

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

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

return new String("foobar"); 

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

return "foobar"; 
+0

Привет, да, это было мое знание, прежде чем ударить это, поэтому я хотел его проверить. Частный флаг - это недостающее звено :) – daschl

Смежные вопросы