Alle Programme haben eine Laufzeitumgebung. Wir neigen dazu, dies zu vergessen, aber es ist da. Standardbibliothek für C, die Systemaufrufe an das Betriebssystem bindet. Objective-C hat eine Laufzeitumgebung, die die gesamte Nachrichtenübergabe umschließt.
Bei Java ist die Laufzeit die JVM. Die meisten bekannten Java-Implementierungen ähneln der HotSpot-JVM, bei der es sich um einen Bytecode-Interpreter und einen JIT-Compiler handelt.
Dies muss nicht die einzige Implementierung sein. Es gibt absolut nichts zu sagen, dass Sie keine standardmäßige lib-esque-Laufzeit für Java erstellen und den Code in systemeigenen Maschinencode kompilieren und diesen innerhalb der Laufzeit ausführen können, die Aufrufe für neue Objekte in mallocs und Dateizugriffe in Systemaufrufe auf der Maschine verarbeitet. Und genau das macht der AOT-Compiler (AOT anstatt JIT). Rufen Sie diese Laufzeit , was Sie ... Sie es eine JVM Implementierung nennen könnte (und es ist die JVM - Spezifikation folgen) oder eine Laufzeitumgebung oder Standard - lib für Java. Es ist da und es macht im Wesentlichen das Gleiche.
Dies könnte entweder durch eine Neuimplementierung erfolgen, javac
um auf den nativen Computer abzuzielen (so wie es GCJ getan hat). Oder Sie können den von generierten Byte-Code javac
in Maschinencode (oder Byte-Code) für eine andere Maschine umwandeln - genau das macht Android. Basierend auf Wikipedia ist es auch das, was Excelsior JET macht ("Der Compiler wandelt den portablen Java-Byte-Code in optimierte ausführbare Dateien für die gewünschte Hardware und das gewünschte Betriebssystem (OS) um"), und dasselbe gilt für RoboVM .
Es gibt zusätzliche Komplikationen mit Java, was bedeutet, dass dies als exklusiver Ansatz sehr schwierig ist. Das dynamische Laden von Klassen ( class.forName()
) oder Proxy-Objekten erfordert eine Dynamik, die von AOT-Compilern nicht einfach bereitgestellt werden kann. Daher müssen die entsprechenden JVMs entweder einen JIT-Compiler (Excelsior JET) oder einen Interpreter (GCJ) enthalten, um Klassen verarbeiten zu können, in die keine Vorkompilierung möglich ist gebürtig.
Denken Sie daran, das ist JVM eine Spezifikation , mit vielen Implementierungen . Die C-Standardbibliothek ist auch eine Spezifikation mit vielen verschiedenen Implementierungen.
Mit Java8 wurde einiges an Arbeit an der AOT-Kompilierung geleistet. Bestenfalls kann man AOT generell nur innerhalb der Grenzen der Textbox zusammenfassen. Beim JVM Language Summit 2015 (August 2015) gab es jedoch eine Präsentation: Java Goes AOT (Youtube-Video). Dieses Video ist 40 Minuten lang und geht auf viele der tieferen technischen Aspekte und Leistungsbenchmarks ein.
gcj
minimal ausführbares BeispielSie können auch eine Open-Source-Implementierung wie
gcj
(jetzt veraltet) beobachten. ZB Java-Datei:Dann kompilieren und ausführen mit:
Jetzt können Sie es dekompilieren und sehen, wie es funktioniert.
file Main.o
sagt, es sei eine Elfendatei.readelf -d Main | grep NEEDED
Das hängt von den dynamischen Bibliotheken ab:Daher muss in libgcj.so die Java-Funktionalität implementiert sein.
Sie können es dann dekompilieren mit:
und sehen genau, wie es umgesetzt wird.
Sieht ähnlich aus wie C ++, viele Namensverwirrungen und indirekte polymorphe Funktionsaufrufe.
Ich frage mich, wie sich die Garbage Collection auswirkt. Es lohnt sich, einen Blick darauf zu werfen : /programming/7100776/garbage-collection-implementation-in-compiled-languages und andere kompilierte Sprachen mit GC wie Go.
Getestet unter Ubuntu 14.04, GCC 4.8.4.
Schauen Sie sich auch https://en.wikipedia.org/wiki/Android_Runtime an , das Backbone von Android 5 und höher, das AOT-Funktionen zur Optimierung von Android-Apps bietet.
quelle