Java AOT编译器如何工作?


18

有几种工具(Excelsior JET等)声称可以将Java应用程序转换为本地可执行文件(*.exe)。但是据我了解,这些工具实际上只是在创建java从外壳程序或命令行调用/执行的本机包装。

如果这种理解是不正确的,我不知道怎么可能。如果正在运行的JVM(java进程)本质上是一种高性能的解释器,则是从Java类文件中动态加载字节码,那么我看不出Java应用程序(用作JVM输入的字节码文件的集合)是怎么回事。真正转换为可执行文件。

这是因为JVM进程已经是本机可执行文件,它将字节码文件集作为输入。如果不完全重写JVM并脱离JVM规范,将这些字节码文件和JVM进程合并为一个统一的本机可执行文件似乎是不可能的。

因此,我问:这些工具实际上是如何将Java类文件“转换”为本地可执行文件的?

Answers:


26

所有程序都具有运行时环境。我们倾向于忘记这一点,但它在那里。C的标准库,用于将系统调用包装到操作系统。Objective-C的运行时包装了所有消息传递。

使用Java,运行时就是JVM。人们熟悉的大多数Java实现都类似于HotSpot JVM,后者是字节码解释器和JIT编译器。

这不一定是唯一的实现。绝对没有什么可以说的,您不能为Java构建标准的lib-esque运行时,也不能将代码编译为本机代码,并在运行时中运行该运行时,该运行时将对新对象的调用处理为malloc,而对文件的访问则作为对计算机上系统调用的处理。这就是Ahead of Time(AOT而不是JIT)编译器的作用。将该运行时称为您将要使用的名称...可以将其称为JVM实现(并且确实遵循JVM规范)或运行时环境或Java的标准库。它在那里,并且基本上执行相同的操作。

可以通过重新实现javac以本机为目标来完成(这就是GCJ所做的事情)。或者可以将生成的字节代码javac转换为另一台机器的机器(或字节)代码来完成-这就是Android所做的。基于Wikipedia的Excelsior JET也是这样做的(“编译器将可移植的Java字节代码转换为针对所需硬件和操作系统(OS)的优化可执行文件”),RoboVM也是如此。

有与Java额外的复杂性,这意味着这是非常难做到的独家方法。动态加载类(class.forName())或代理对象需要AOT编译器不容易提供的动态,因此它们各自的JVM还必须包括JIT编译器(Excelsior JET)或解释器(GCJ)来处理无法预编译到的类本机。

请记住,JVM是一个规范具有许多实现。C标准库也是具有许多不同实现的规范

使用Java8,已经在AOT编译上完成了大量工作。充其量,人们只能在文本框的范围内概括AOT。但是,在2015年JVM语言峰会(2015年8月)上,有一个演示文稿:Java Goes AOT(youtube视频)。该视频长40分钟,涉及许多更深层次的技术方面和性能基准。


抱歉,我对此并不了解,但这是否意味着Java现在是本地的?还是意味着有一个新的编译器标志,如果需要的话,该标志允许我们将Java程序编译为本机代码,并且我们仍然可以选择编译为字节码?
帕维尔

@ paulpaul1076我建议您观看链接的视频。其中包含的内容远远超出我可以合理评论的范围。

4

gcj 最小的可运行示例

您还可以观察到开源实现,例如gcj(现已过时)。例如Java文件:

public class Main {
    public static void main(String args[]) {
        System.out.println("hello world");
    }
}

然后编译并运行:

gcj -c Main.java
gcj --main=Main -o Main Main.o
./Main

现在,您可以自由对其进行反编译,并查看其工作原理。

file Main.o 说这是一个精灵文件。

readelf -d Main | grep NEEDED 说它取决于动态库:

0x0000000000000001 (NEEDED)             Shared library: [libgcj.so.14]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

因此libgcj.so必须是实现Java功能的位置。

然后可以使用以下命令对其进行反编译:

objdump -Cdr Main.o

并确切了解它是如何实现的。

看起来很像C ++,有很多名称修饰和间接多态函数调用。

我想知道垃圾收集是如何开始的。值得研究一下:https : //stackoverflow.com/questions/7100776/garbage-collection-implementation-in-compiled-languages和其他带有GC的编译语言,如Go。

在Ubuntu 14.04,GCC 4.8.4上测试。

还可以查看https://en.wikipedia.org/wiki/Android_Runtime,它是Android 5及更高版本的骨干,它执行完整的AOT来优化Android应用程序。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.