6

gebenen Argumente Ich habe einige auf JLS Lesung bis 15.7.4 und 15.12.4.2, aber es garantiert nicht, dass es nicht sein Compiler/Laufzeitoptimierung das wäre ändern Sie die Reihenfolge, in der Methodenargumente ausgewertet werden.Ist Java Auswerteauftrag in diesem Fall der Methodenaufruf garantiert und in

Angenommen, den folgenden Code:

public static void main (String[] args) { 
    MyObject obj = new MyObject(); 
    methodRelyingOnEvalOrder(obj, obj.myMethod()); 
} 

public static Object methodRelyingOnEvalOrder(MyObject obj, Object input) { 
    if (obj.myBoolean()) 
    return null; 
    else 
    return input; 
} 

ist sichergestellt, dass der Compiler oder Laufzeit eine falsche Optimierung nicht tun wie die folgenden? Diese Optimierung mag korrekt aussehen, aber sie ist falsch, wenn die Reihenfolge der Auswertung wichtig ist.

In dem Fall, wo obj.myMethod Aufruf den Wert ändert, der von obj.myBoolean zurückgegeben wird, ist es entscheidend, dass obj.myMethod zunächst als methodRelyingOnEvalOrder erfordern diese Veränderung zunächst geschehen aufgerufen werden.

//******************************* 
//Unwanted optimization possible: 
//******************************* 
public static void main (String[] args) { 
    MyObject obj = new MyObject(); 
    methodRelyingOnEvalOrder(obj); 
} 

public static Object methodRelyingOnEvalOrder(MyObject obj) { 
    if (obj.myBoolean()) 
    return null; 
    else 
    return obj.myMethod(); 
} 
//******************************* 

Wenn möglich, Sie einige Quellen oder Java-Dokumentation zeigen, dass Ihre Antwort unterstützt.

Hinweis: Bitte nicht bitten, den Code neu zu schreiben. Dies ist ein spezieller Fall, in dem ich die Evaluierungsauftragsgarantie und die Compiler/Laufzeitoptimierungsgarantie in Frage stelle. Die Ausführung von obj.myMethod muss in der main Methode geschehen.

+1

Sie können sicher sein, dass 'javac' fast überhaupt keine Optimierungen durchführt, alles wird vom JIT erledigt. Während es den Methodenaufruf möglicherweise neu anordnet oder sogar eliminiert, sollte das Endeverhalten gleich sein. –

Antwort

6

Das Bit des JLS Sie genannt (15.7.4) tut Garantie, dass:

Jedes Argument Ausdruck vor jedem Teil dieses Argument Ausdruck ihr Recht vollständig ausgewertet werden angezeigt.

und auch in 15.12.4.2:

Auswertung geht dann weiter, die Argumentwerte verwendet wird, wie unten beschrieben.

Die „erscheint“ Teil für einige Optimierung erlaubt, aber es muss nicht sichtbar sein. Die Tatsache, dass alle Argumente ausgewertet werden vor "Auswertung fährt fort" zeigt, dass die Argumente wirklich vollständig ausgewertet werden, bevor die Methode ausgeführt wird. (Oder zumindest, das ist das sichtbare Ergebnis.)

So zum Beispiel, wenn Sie Code hatte:

int x = 10; 
foo(x + 5, x + 20); 

es möglich sein würde, das optimieren sowohl x + 5 und x + 20 parallel zu bewerten: Es gibt keine Möglichkeit, das zu entdecken.

Aber im Fall, dass Sie gegeben haben, Sie würde der Lage sein, den Anruf zu obj.myMethod nach dem Aufruf von obj.myBoolean(), auftreten, zu erkennen, so dass würde überhaupt nicht eine gültige Optimierung sein.

Kurz gesagt: Sie können davon ausgehen, dass hier alles auf die offensichtliche Art und Weise ausgeführt wird.

+0

Können Sie weiter erklären, was die JLS mit _bedeutet und warum es nicht _is_ ist? Und was ist nicht sichtbar? – ADTC

+0

@ADTC: Es bedeutet, dass Sie hier keine Optimierung erkennen können - es handelt sich um eine wirklich unsichtbare Optimierung, falls überhaupt eine angewendet wird. –

+0

Mein Bauch stimmt zu, aber was dieser Abschnitt eigentlich sagt (der Teil, den Sie weggelassen haben) ist: Wenn die Auswertung eines Argumentausdrucks abrupt abgeschlossen wird, dann scheint kein Teil eines Argumentausdrucks rechts davon ausgewertet worden zu sein , zumindest aus dem, was ich in diesem Abschnitt sehe, explizit angeben, was die scheinbare Bewertungsreihenfolge sein sollte, wenn keine der Bewertungen abrupt abgeschlossen wird. –

5

Neben der Argumentauswertungsreihenfolge, die Übersicht über die vorgeformten Schritte, wenn eine Methode aufgerufen wird, und deren Reihenfolge, in Abschnitt 15.12.4. Run-Time Evaluation of Method Invocation erläutert, macht deutlich, dass alle Argument Auswertungen durchgeführt werden, bevor das Verfahren der Code ausgeführt wird. Quote:

Zur Laufzeit benötigt Methodenaufruf fünf Schritte. Zuerst kann ein Ziel Referenz berechnet werden. Zweitens sind die Argumentausdrücke ausgewertet. Drittens ist die Zugänglichkeit der aufzurufenden Methode geprüft. Viertens ist der eigentliche Code für die auszuführende Methode lokalisiert. Fünftens wird ein neuer Aktivierungsrahmen erstellt, bei Bedarf wird die Synchronisierung durchgeführt, und die Steuerung wird an den Methodencode übergeben.

Der Fall, dass Sie präsentiert, wo ein Argument nur ausgewertet wird, nachdem Steuerung auf den Methodencode übertragen worden ist die Frage.

+0

Danke für Ihren Beitrag. Ich kann nur eine Antwort akzeptieren, aber ich habe Sie upvoted :) – ADTC

Verwandte Themen