7

Mam trudności ze znalezieniem informacji o możliwości eliminacji kod javac Addkod javac możliwości eliminacji

Czytałem, że jeśli masz coś podobnego Poniżej if -statement zostaną wyeliminowane:

static final boolean DEBUG = false; 

if (DEBUG) System.out.println("Hello World!"); // will be removed 

Ale jak o tym, na przykład:

static final int VALUE = 3; 

if (VALUE > 9) System.out.println("VALUE > 9 ???"); // will this be removed? 

Lub jes s:

static final SomeEnum VALUE = SomeEnum.FOO; 

if (VALUE==SomeEnum.BAR) System.out.println("Bar???"); // will this be removed? 

Ponieważ jest to bardzo trudne/niemożliwe do analizy programu, aby znaleźć wszystkie martwe kod (prawdopodobnie podobny do problemu stopu), to sobie wyobrazić, że istnieją tylko kilka dobrze zdefiniowane konstrukcje (jak pierwszy przykład powyżej), który javac rozpozna i usunie niezawodnie. Czy istnieje obszerna lista tych konstrukcji?

+1

Czy próbowałeś go zobaczyć? 'javap -c' sprawi, że będzie to całkiem jasne ... –

+2

@JonSkeet Jeszcze nie, ponieważ miałem nadzieję znaleźć listę tych konstrukcji, więc nie muszę ich wypróbowywać jeden po drugim. Poza tym prawdopodobnie nie będę w stanie wymyślić wszystkich możliwości ... Ale, na dwa powyższe przykłady, oczywiście, masz rację, mogę sprawdzić ... –

+1

Dla rekordu pierwsze dwa są eliminowane trzeci nie jest. – assylias

Odpowiedz

7

assylias wydaje się, że znalazłem odpowiedź (pozwól mi po prostu umieścić to wszystko razem):

Chapter "14.21. Unreachable Statements" of the JLS Określa, że ​​w ogóle, każdy nieosiągalny oświadczenie w kodzie jest uważany za kompilacji błędów, z jedynym wyjątkiem jest specjalny leczenie if -statements specjalnie pozwalają na kompilacji warunkowej.

Dlatego tylko skonstruować że może wynik w eliminacji kodu (! Jeśli kompilator zdecyduje się to zrobić) to:

if (compileTimeConstantExpression) { 
    doThis(); // may be removed if compileTimeConstantExpression == false; 
} else { 
    doThat(); // may be removed if compileTimeConstantExpression == true; 
} 

(else -part jest opcjonalne, oczywiście)

Wszystkie inne konstrukcje, które pozwalają na eliminację kodu, jak na przykład while (false) ..., są niedozwolone i powodują zamiast tego kompilację warunkową zamiast błędu kompilacji.

Definicję tego, co stanowi akceptowalną wersję compileTimeConstantExpression można znaleźć pod adresem chapter "15.28. Constant Expressions" of the JLS. Kolejna świetna strona z dodatkowymi przykładami znajduje się tutaj: Compile Time Constants in Java

Uwaga: Nie ma wymogu, aby kompilator usuwał "nieosiągalne" sekcje z if -stamentu. javac wydaje się robić to niezawodnie, ale inne kompilatory mogą nie. Jedynym sposobem na uzyskanie pewności jest sprawdzenie danych wyjściowych poprzez dekompilację, na przykład za pomocą javap -c, zgodnie z sugestią Jona Skeeta.

0

widzę, że za 2 przykładzie zostanie usunięty zbyt

to była moja klasa

public class Test { 

    public static void main(String[] args) throws Exception{ 
     final int VALUE = 3; 
     if (VALUE > 9) System.out.println("VALUE > 9 ???"); 
    } 
} 

i to dekompilowana wersji

Compiled from "Test.java" 
public class Test extends java.lang.Object{ 
public Test(); 
    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: return 

} 
4

Mam biegać kilka testów i wydaje (logicznie), że javac usuwa kod iif warunek to constant expression, który ocenia jako fałszywy.

Podsumowując, wyrażenia stałe są wyrażeniami, które wykorzystują tylko stałe jako operandy, tj. Prymitywy, ciągi znaków i prymitywy ciągów znaków lub final, które zostały zainicjowane wartością stałą.

Należy pamiętać, że jest to kompilator zależne jako JLS nie wymusza kompilator będzie taki mądry, jak wyjaśniono na samym dole 14.21:

kompilator optymalizujący może zrozumieć, że oświadczenie x = 3; nigdy nie zostanie wykonany i może wybrać pominięcie kodu dla tego polecenia z wygenerowanego pliku klasy.

+0

To brzmi, jakby miało to sens ... Czy wiesz, czy jest to gdzieś określone w dokumentach? +1 –

+0

@MarkusA. Zobacz moją edycję. – assylias

+0

Przygotowałem odpowiedź na podstawie podanych linków i informacji. Uważam, że jest to bardziej kompletne/jasne w ten sposób. Ale wciąż uważam, że zasługujesz na uznanie za dostarczenie początkowych elementów. Zastanawiałem się, czy chciałbyś jeszcze raz zaktualizować swoją odpowiedź (możesz kopiować części z mojej), abym mógł zaakceptować twoje i usunąć moje. :) –

0

Przypuszczam, że jest to specyficzne dla implementacji (Oracle, IBM, ...).

Jeśli jesteś zainteresowany w wersji Oracle, dobrym miejscem do rozpoczęcia poszukiwań zasobów byłoby OpenJDK projekt: http://openjdk.java.net/groups/compiler/