Tous les programmes ont un environnement d'exécution. Nous avons tendance à oublier cela, mais c'est là. Lib standard pour C qui encapsule les appels système vers le système d'exploitation. Objective-C a son runtime qui encapsule tout son message qui passe.
Avec Java, le runtime est la JVM. La plupart des implémentations Java que les gens connaissent sont similaires à la machine virtuelle Java HotSpot qui est un interpréteur de code octet et un compilateur JIT.
Cela ne doit pas être la seule implémentation. Rien ne dit que vous ne pouvez pas créer un runtime lib-esque standard pour Java et compiler le code en code machine natif et l'exécuter dans le runtime qui gère les appels de nouveaux objets dans mallocs et l'accès aux fichiers dans les appels système sur la machine. Et c'est ce que fait le compilateur Ahead Of Time (AOT plutôt que JIT). Appelez cette exécution ce que vous ... vous pourriez l' appeler une implémentation machine virtuelle Java (et il ne suit la spécification JVM) ou un environnement d'exécution ou lib standard pour Java. C'est là et ça fait essentiellement la même chose.
Cela pourrait être fait soit en réimplémentant javac
pour cibler la machine native (c'est un peu ce que GCJ a fait). Ou cela pourrait être fait en traduisant le code d'octet généré par javac
en code machine (ou octet) pour une autre machine - c'est ce que fait Android. Basé sur Wikipedia, c'est aussi ce que fait Excelsior JET ("Le compilateur transforme le code d'octet Java portable en exécutables optimisés pour le matériel et le système d'exploitation (OS) souhaités"), et il en va de même pour RoboVM .
Il y a des complications supplémentaires avec Java, ce qui signifie qu'il est très difficile de le faire en tant qu'approche exclusive. Le chargement dynamique des classes ( class.forName()
) ou des objets mandatés nécessite une dynamique que les compilateurs AOT ne fournissent pas facilement et leurs JVM respectives doivent donc également inclure un compilateur JIT (Excelsior JET) ou un interprète (GCJ) pour gérer les classes qui ne peuvent pas être précompilées dans originaire de.
N'oubliez pas que la JVM est une spécification , avec de nombreuses implémentations . La bibliothèque standard C est également une spécification avec de nombreuses implémentations différentes.
Avec Java8, un bon travail a été fait sur la compilation AOT. Au mieux, on ne peut résumer AOT en général que dans les limites de textbox. Cependant, lors du JVM Language Summit pour 2015 (août 2015), il y avait une présentation: Java Goes AOT (vidéo youtube). Cette vidéo dure 40 minutes et aborde de nombreux aspects techniques plus approfondis et des performances de référence.
gcj
exemple exécutable minimalVous pouvez également observer une implémentation open source comme
gcj
(maintenant obsolète). Exemple de fichier Java:Ensuite, compilez et exécutez avec:
Vous êtes maintenant libre de le décompiler et de voir comment cela fonctionne.
file Main.o
dit que c'est un fichier elfe.readelf -d Main | grep NEEDED
dit que cela dépend des bibliothèques dynamiques:Donc libgcj.so doit être l'endroit où la fonctionnalité Java est implémentée.
Vous pouvez ensuite le décompiler avec:
et voyez exactement comment il est mis en œuvre.
Ressemble beaucoup au C ++, à beaucoup d'appels de noms et de fonctions polymorphes indirectes.
Je me demande comment la collecte des ordures intervient. Cela vaut la peine d'être examiné: /programming/7100776/garbage-collection-implementation-in-compiled-languages et d'autres langages compilés avec GC comme Go.
Testé sur Ubuntu 14.04, GCC 4.8.4.
Jetez également un œil à https://en.wikipedia.org/wiki/Android_Runtime , l'épine dorsale d'Android 5, qui fait le plein AOT pour optimiser les applications Android.
la source