2016-02-13 21 views
5

Ho una semplice classe per gli scopi illustrativi:Perché il compilatore Java non sta ottimizzando un metodo banale?

public class Test { 

    public int test1() { 
     int result = 100; 
     result = 200; 
     return result; 
    } 

    public int test2() { 
     return 200; 
    } 
} 

Il bytecode generato dal compilatore (ispezionati da javap -c Test.class) è la seguente:

public int test1(); 
Code: 
    0: bipush  100 
    2: istore_1 
    3: sipush  200 
    6: istore_1 
    7: iload_1 
    8: ireturn 

public int test2(); 
Code: 
    0: sipush  200 
    3: ireturn 

Perché il compilatore non ottimizzando la test1 metodo per lo stesso bytecode prodotto per il metodo test2? Mi aspetto che almeno eviti l'inizializzazione ridondante della variabile result considerando che è facile concludere che il valore 100 non viene utilizzato affatto.

Ho osservato questo con entrambi il compilatore Eclipse e javac. Versione

javac: 1.8.0_72, installato come parte del JDK insieme a Java:

Java(TM) SE Runtime Environment (build 1.8.0_72-b15) 
Java HotSpot(TM) 64-Bit Server VM (build 25.72-b15, mixed mode) 
+6

Il * Java Language Specification * non richiede alcuna ottimizzazione come questa, quindi non è significativo parlare di "compilatore" come se ce ne fosse solo uno. Dovresti indicare quale compilatore stai usando. – ruakh

+5

la risposta classica è che le ottimizzazioni vengono eseguite nella JVM (http://stackoverflow.com/questions/5981460/optimization-by-java-compiler) – wero

+0

@ruakh Buona osservazione; aggiunto informazioni sul compilatore. –

risposta

4

Una tipica macchina virtuale Java ottimizza il programma in fase di runtime, non durante la compilazione. Al momento dell'esecuzione, la JVM conosce molto di più sulla tua applicazione, sia sul comportamento effettivo del tuo programma sia sull'hardware effettivo su cui il tuo programma viene eseguito.

Il codice byte è semplicemente una descrizione del comportamento del programma. Il runtime è libero di applicare qualsiasi ottimizzazione al codice byte.

Naturalmente, si può sostenere che tali ottimizzazioni banali potrebbero essere applicate anche durante la compilazione, ma in generale ha senso non distribuire le ottimizzazioni su più passaggi. Qualsiasi ottimizzazione sta effettivamente causando un loos di informazioni sul programma originale e questo potrebbe rendere altre ottimizzazioni impossibili. Detto questo, non tutte le "migliori ottimizzazioni" sono sempre ovvie. Un approccio semplice a questo è semplicemente eliminare (quasi) tutte le ottimizzazioni durante la compilazione e applicarle in fase di esecuzione.

+0

sì - almeno le informazioni del numero di riga andrebbero perse, quindi lo stacktrace non sarà accurato; e il debug sarà più difficile. – ZhongYu

4

JVM ottimizza il bytecode, creando qualcosa che si chiama una cache codice. A differenza del C++, JVM può raccogliere molti dati sul tuo programma, ad esempio, Quanto è caldo il ciclo?, Questo blocco di codice vale anche la pena di essere ottimizzato?, ecc. Quindi l'ottimizzazione qui è molto utile e spesso produce risultati migliori.

Se si ottimizza quando si traduce da java in bytecode (vale a dire, quando si chiama javac), il codice potrebbe essere ottimale per il computer, ma non per un po 'diverso piattaforma. Quindi non ha senso ottimizzare qui.

Come esempio, si supponga che il programma utilizzi la crittografia AES. Le moderne CPU hanno set di istruzioni specifiche per AES, con hardware speciale per rendere la crittografia molto più veloce.

Se javac tenta di ottimizzare al momento della compilazione, allora sarà o

  • ottimizzare le istruzioni a livello di software, nel qual caso si programma di beneficio solito dalle CPU moderna, o,
  • sostituire le tue istruzioni AES con equivalenti istruzioni CPU-AES, supportate solo su nuove CPU, che ridurranno la tua compatibilità.

Se invece javac li lascia come è nel byptcode, poi la JVM in esecuzione su CPU più recenti può riconoscerli come AES e sfruttare questa capacità di CPU, mentre le JVM in esecuzione su CPU più anziani di loro in grado di ottimizzare a livello software in fase di runtime (cache del codice), fornendo entrambi l'ottimity e .

Problemi correlati