我只是想知道如何摆脱 java jre 依赖并生成本机代码并将编译后的代码作为应用程序交付?
那么有可能吗?
PS我知道gcj编译器它在做什么?
编译后的字节码仍将依赖于 java 虚拟机。JIT 无法在 JVM 容器之外创建“有意义”的代码。是的,结果是一堆针对目标平台的有效指令。但是您仍然需要实际的堆栈、堆和垃圾收集器(仅举几个必需的构建块)。
Excelsior有一个非常好的 Java2Native 编译器。我很想使用它,但遗憾的是,我们的项目需要 8 个小时才能使用此编译器进行编译。该应用程序的最终速度令人印象深刻。
理论上,可以将任何一种语言的解释器转换为编译器,生成该语言的本机代码。这与称为Futamura 投影的一系列方程有关。高级思想本质上是“欺骗”您如何定义编译器。假设对于某种语言 LI 有一个解释器 I(p),给定一个用语言 L 编写的程序 p,解释该程序。现在,我假设解释器 I 直接用机器代码表示。进一步假设我有一个名为mix
该程序的程序,给定一个机器代码程序和该程序的一系列输入,生成一个新的机器代码程序,该程序是初始程序,其输入固定为指定输入。例如,如果我编译了这个 C++ 程序:
#include <iostream>
using namespace std;
int main() {
string message;
cin >> message;
cout << message << endl;
}
然后mix
将程序与输入“Hello”混合使用,我会得到一个始终打印出消息“Hello”的程序。换句话说,就好像我写了这个程序:
#include <iostream>
using namespace std;
int main() {
cout << "Hello" << endl;
}
事实证明,构建这个程序是可能的。例如,我可以通过查看机器代码、查看您尝试从控制台读取输入的每个地方,然后将其替换为调用函数的代码来代替从硬编码字符串中读取的代码来做到这一点。
现在,考虑一下如果你以mix
解释器 I 和某个程序 p 作为输入来运行这个程序会发生什么。那么这个结果将是一个机器代码程序,它相当于我在输入 p 上运行的程序。换句话说,你刚刚构建了一个机器代码程序,它模拟了如果你在程序上运行解释器会发生什么——这是一个执行程序 p 的机器代码程序!
当然,这种结构是完全不切实际的。据我所知,没有人编写过mix
,如果他们这样做了,那么您通过将解释器转换为编译器来编写的任何程序都将非常低效,因为它根本不会被优化。
至于您最初关于是否可以采用 JVM 的 JIT 并使用它为 Java 程序生成原始机器代码的问题,我不确定,因为我没有查看源代码,但我非常怀疑。机器代码几乎肯定包含会为特定任务(例如,垃圾收集、类加载等)回调到 JVM 中的钩子,这会使生成的代码无法在独立环境中工作。但是,尝试这样做是一个非常酷的想法,我希望这个答案能对它背后的理论有所启发!
请注意,这个问题类似于“我可以摆脱 Windows 并让我的 Windows 程序在没有操作系统的裸机上运行”吗?
Java 程序期望大量类随时可用,这是 JRE 提供的,任何编译器或仿真器也必须提供。
然而,您可以做的是查看一个启动器,它允许您将自己的 JRE 与您的应用程序一起使用 - 这仅适用于 JRE 的平台,但您已经愿意成为特定于平台的。有几个存在 - 我鼓励您查看 Stack Overflow 上关于如何做到这一点的许多问题。