Gibt es Inline-Funktionen in Java?


112

Gibt es ein Konzept für Inline-Funktionen in Java oder wird es durch etwas anderes ersetzt? Wenn ja, wie wird es verwendet? Ich habe gehört , dass public, staticund finalMethoden sind die Inline - Funktionen. Können wir unsere eigene Inline-Funktion erstellen?



3
Als kleiner Kommentar ist vorzeitige Optimierung die Wurzel allen Übels. Ohne die Natur von öffentlich, statisch und endgültig vollständig zu verstehen, können Sie die Auswirkungen von Inlining nicht wirklich verstehen - und das hängt von der von Ihnen verwendeten JVM ab. Stellen Sie sicher, dass Sie zuerst antworten, warum Sie etwas einbinden müssen: Es ist fast sicher, dass es höhere ROI-Optimierungen gibt, die Sie an anderer Stelle durchführen können.
Nathaniel Ford

Antworten:


123

In Java werden die Optimierungen normalerweise auf JVM-Ebene durchgeführt. Zur Laufzeit führt die JVM eine "komplizierte" Analyse durch, um zu bestimmen, welche Methoden inline sind. Es kann beim Inlining aggressiv sein, und die Hotspot-JVM kann tatsächlich nicht endgültige Methoden inline.

Die Java-Compiler inline fast nie einen Methodenaufruf (die JVM erledigt das alles zur Laufzeit). Sie führen Inline-Kompilierungszeitkonstanten durch (z. B. endgültige statische Grundwerte). Aber keine Methoden.

Für mehr Ressourcen:

  1. Artikel: Die Java HotSpot Performance Engine: Beispiel für das Inlining von Methoden

  2. Wiki: Inlining in OpenJDK , nicht vollständig ausgefüllt, enthält jedoch Links zu nützlichen Diskussionen.


15

Nein, in Java gibt es keine Inline-Funktion . Ja, Sie können eine öffentliche statische Methode an einer beliebigen Stelle im Code verwenden, wenn Sie in eine öffentliche Klasse eingefügt werden. Der Java-Compiler führt möglicherweise eine Inline-Erweiterung für eine statische oder endgültige Methode durch, dies ist jedoch nicht garantiert.

Typischerweise werden solche Codeoptimierungen vom Compiler in Kombination mit dem JVM / JIT / HotSpot für Codesegmente durchgeführt, die sehr häufig verwendet werden. Auch andere Optimierungskonzepte wie die Registerdeklaration von Parametern sind in Java nicht bekannt.

Optimierungen können nicht durch Deklaration in Java erzwungen werden, sondern durch Compiler und JIT. In vielen anderen Sprachen sind diese Deklarationen oft nur Compiler-Hinweise (Sie können mehr Registerparameter deklarieren als der Prozessor, der Rest wird ignoriert).

Das Deklarieren von Java-Methoden als statisch, endgültig oder privat ist ebenfalls ein Hinweis für den Compiler. Sie sollten es verwenden, aber keine Garantien. Die Java-Leistung ist dynamisch und nicht statisch. Der erste Aufruf eines Systems ist aufgrund des Ladens der Klasse immer langsam. Die nächsten Aufrufe sind schneller, aber je nach Speicher und Laufzeit werden die häufigsten Aufrufe im laufenden System optimiert, sodass ein Server zur Laufzeit möglicherweise schneller wird!


3
finalMachen Sie keinen Einfluss auf JIT Inlining
Steve Kuo

1
+1, Aber wie können wir testen, ob die kompilierte Version einer Methode inline ist?
Pacerier

@ Pacerier Aber warum sollten wir testen, ob etwas inline ist?
Arne Burmeister

14

Java bietet keine Möglichkeit, manuell vorzuschlagen, dass eine Methode eingebunden werden soll. Wie @notnoop in den Kommentaren sagt, wird das Inlining normalerweise von der JVM zur Ausführungszeit durchgeführt.


3
Die meisten Java-Compiler inline nie Methodenaufrufe. Meistens macht die JVM das.
Notnoop

Vielen Dank für die Klarstellung. Ich war mir nicht sicher, in welcher Phase das genau passiert ist. Ich werde meinen Beitrag bearbeiten, um dies widerzuspiegeln.
Thomas Owens

@ ThomasOwens tut es, aber es ist nicht öffentlichjdk.internal.vm.annotation.ForceInline
Eugene

4

Was Sie oben gesagt haben, ist richtig. Manchmal werden endgültige Methoden als Inline-Methoden erstellt, aber es gibt keine andere Möglichkeit, eine Inline-Funktion in Java explizit zu erstellen.


5
Es wird nicht garantiert, dass die endgültigen Methoden inline sind.
Thomas Owens

4
Bei HotSpot macht das Hinzufügen finalnicht einmal einen Unterschied, ob die Methode inline ist oder nicht.
Tom Hawtin - Tackline

4
@ Thomas - weshalb ich sagte "Manchmal endgültige Methoden ..."
GreenieMeanie

@ TomHawtin-Tackline Hast du eine maßgebliche Quelle dafür? Soweit ich weiß, können endgültige Methoden ohne Verwendung eines Typschutzes eingebunden werden, was bedeutet, dass der Modifikator das Inlinen der Methode effizienter macht als ohne den Modifikator. Ich weiß, dass Jikes RVM dies bei der Entscheidung über Inline berücksichtigt. Sind Sie sicher, dass HotSpot nichts Ähnliches tut?
Jannik Jochem

2

Beispiel aus dem wirklichen Leben:

public class Control {
    public static final long EXPIRED_ON = 1386082988202l;
    public static final boolean isExpired() {
        return (System.currentTimeMillis() > EXPIRED_ON);
    }
}

In anderen Klassen kann ich dann beenden, wenn der Code abgelaufen ist. Wenn ich auf die Variable EXPIRED_ON aus einer anderen Klasse verweise, ist die Konstante inline zum Bytecode, was es sehr schwierig macht, alle Stellen im Code zu finden, die das Ablaufdatum überprüfen. Wenn die anderen Klassen jedoch die Methode isExpired () aufrufen, wird die eigentliche Methode aufgerufen. Dies bedeutet, dass ein Hacker die Methode isExpired durch eine andere ersetzen kann, die immer false zurückgibt.

Ich bin damit einverstanden, dass es sehr schön wäre, einen Compiler zu zwingen, die statische endgültige Methode allen Klassen zuzuordnen, die darauf verweisen. In diesem Fall müssen Sie nicht einmal die Control-Klasse einschließen, da sie zur Laufzeit nicht benötigt wird.

Nach meinen Recherchen ist dies nicht möglich. Möglicherweise können einige Obfuscator-Tools dies tun, oder Sie können Ihren Erstellungsprozess ändern, um Quellen vor dem Kompilieren zu bearbeiten.

Versuchen Sie, die andere Klasse ohne die Control-Klasse im Klassenpfad auszuführen, um zu beweisen, ob die Methode aus der Steuerungsklasse während der Kompilierung inline zu einer anderen Klasse gestellt wird.


2

Nun, es gibt Methoden, die in Java als "Inline" -Methoden bezeichnet werden könnten, aber abhängig von der JVM. Wenn der Maschinencode der Methode nach dem Kompilieren weniger als 35 Byte beträgt, wird er sofort an eine Inline-Methode übertragen. Wenn der Maschinencode der Methode weniger als 325 Byte beträgt, kann er je nach JVM in eine Inline-Methode übertragen werden.


1
Dies sind Standardwerte für die VM von Oracle, siehe docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
rmuller

0

Es scheint also nicht so zu sein, aber Sie können diese Problemumgehung mit Guave oder einer äquivalenten Implementierung der Funktionsklasse verwenden, da diese Klasse extrem einfach ist, z.

    assert false : new com.google.common.base.Function<Void,String>(){
        @Override public String apply(Void input) {
            //your complex code go here
            return "weird message";
        }}.apply(null);

Ja, dies ist toter Code, nur um zu veranschaulichen, wie ein komplexer Codeblock (innerhalb von {}) erstellt wird, um etwas so Spezifisches zu tun, dass wir keine Methode dafür erstellen sollten, AKA inline!


Scheint eine vernünftige Idee zu sein. Haben Sie eine Version davon, die die allgemeinen Google-Bibliotheken nicht verwendet?
Ragerdl

0

Java9 verfügt über einen "Ahead of Time" -Compiler, der zur Kompilierungszeit mehrere Optimierungen durchführt und nicht zur Laufzeit, was als Inlining angesehen werden kann.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.