我能将Java编译为本地代码吗?

97

有没有一种方法可以将Java代码编译成独立的(或库)机器码,而不需要JVM?


8
如果您的兴趣是速度,除非您考虑到HotSpot(Sun的JVM)不支持的平台,否则不要费心。HotSpot会在执行路径的“热点”(即经常运行的代码)处即时将字节码编译为本机代码,而它做得非常好。但是,如果您想避免需要JVM,那么可以考虑James向您推荐的gcj。 - T.J. Crowder
3
另一个原因是防止Java反编译器。至于HotSpot vs本地编译器(vs JRockit vs IBM vs GCC vs Visual C++ vs手写CPU指令的十六进制代码)的性能,这取决于应用程序,所以可能会有所不同。 - Dmitry Leskov
1
我发现Oracle为其Oracle数据库开发了一个有趣的工具,称为JServer Accelerator。它还被设计成在某种程度上依赖于平台,通过编译而不是字节码生成C代码。http://docs.oracle.com/cd/A87860_01/doc/java.817/a83727/jtools5.htm - supernova
@Igal:提醒一下,"版主"几乎全部是3000+声望的用户。关闭标记并不总是完美反映关闭原因,但我能理解为什么它被关闭了。由于长度和措辞,这看起来接近于"不是一个问题"的边缘,尽管我同意它刚好处在边缘的右侧。 - CodeMouse92
5个回答

41

曾经有一个称为GCJ的工具是GCC的一部分,但现在已经被删除。现在,GCC网站中的所有链接都会重定向到它们的非GCJ等效链接。

注意:评论都是针对我最初的回答,说你可以使用GCJ将Java编译成本地代码。


2
是的,gcj 是最著名的一个。@isola009:请记住,当编译为本机代码时,您可能会使用 Java 通常默认拥有的*库的子集(可能是显著小的子集)进行工作。据所有人所说,Gnu 的很不错,但远远落后于当前的 JDK。 - T.J. Crowder
它在所有以1.2开头的JDK中都远远落后。我遇到了许多支持问题,因为人们意外运行了GNU classpath而不是Java,但是所有这些问题都毫无例外地通过卸载它并使用Sun JDK得到了解决。 - user207421
Excelsior JET 包含 Java SE 6 标准库的许可实现,并已通过官方合规性测试(JCK)。目前它处于 6u18 级别,下一个版本预计将支持 6u20。 - Dmitry Leskov

40

是的!

Oracle一直在开发GraalVM,它支持原生映像。请查看这里:https://www.graalvm.org/

原生映像 GraalVM SDK中的原生映像功能有助于提高Java应用程序的启动时间,并使其占用更小的空间。实际上,它将在JVM上运行的字节码转换为特定操作系统/平台的本机代码,这就是其性能的来源。它使用激进的提前编译(AOT)优化来实现良好的性能。

了解更多:

Micronaut平台使用GraalVM来创建本地微服务:

简单示例

 public class HelloWorld {
     public static void main(String[] args) {
         System.out.println("Hello, Native World!");
     }
 }

编译Java:
 javac HelloWorld.java

编译为本机代码:
 native-image HelloWorld

运行(只需要可执行文件):
 ./HelloWorld 

输出

 Hello, Native World!

遗憾的是,即使是这个项目也不稳定适用于生产环境,而且使用Swing API仍然不受支持/存在缺陷:https://github.com/oracle/graal/issues/1327 - BullyWiiPlaza
1
GraalVM 19.0发布:“GraalVM终于成熟并准备好用于生产环境”。当然,可能会存在一些错误和尚未完善的功能。但Twitter正在使用它来支持其生产系统,因此我不同意你的第一个说法。 - Rob Audenaerde
1
我的个人经验是,在 Windows 上只有玩具程序可以运行,但任何更高级的程序和/或使用 GUI 时都还不够稳定。Twitter 可能在没有任何 GUI 的情况下使用 Linux,但他们可能也使用商业版本,而我只尝试过社区版。它可能适用于某些用例,但 Java Windows 桌面应用程序不是其中之一,这仍然使项目稍微令人失望。Excelsior JET 可以可靠地完成这项工作,但现在已经停止了。 - BullyWiiPlaza
还需要.jar文件。 - undefined

19

Excelsior JET 是一款商用的 Java 到本地代码编译器。然而,它已于2019年5月停止开发。


3
以防万一,非商业项目可以免费获得许可证。 - Dmitry Leskov
1
它与RoboVM相比如何? - Janus Troelsen
2019年5月15日,Excelsior JET已经停止使用。请参见:https://en.wikipedia.org/wiki/Excelsior_JET - Stephan

9
是的,JVM 中的 JIT 正是为您做到了这一点。
事实上,它可以产生比预先编译代码更快的代码,因为它可以基于运行时代码的使用情况生成针对特定平台进行优化的代码。
即使有很高的百分比被编译成本地代码,JVM 也总是参与其中,因为您可以动态加载和运行字节码。

22
没错,你说得对,JIT可以做到这一点,并且做得非常好。它不会生成独立的可执行文件,但是因为OP没有问及这个,所以这点并不重要。 - Bill K
2
你似乎在暗示只有JIT才能进行平台特定的优化。我认为只要你在运输字节码,就可以实现这一点。ART在安装时将字节码编译为本地代码,它不是JIT。Peter,你对此有什么评论吗? - Janus Troelsen
2
OP提到了独立运行,这意味着完全排除任何形式的JIT:虽然JIT可以即时生成本地代码,但它永远不是独立的。 - StormByte
1
@KurtFitzner,我认为您对JIT编译器的作用有着非常不同的看法。它会编译成本地代码,不涉及解释。 - Peter Lawrey
3
我不相信JIT编译器能够像本地AOT编译器/链接器那样进行深度优化:使用完整优化进行编译和链接应该会让任何计算机崩溃;如果没有,那么编译器就没有尽最大努力进行优化。 - Johan Boulé
显示剩余5条评论

0

另一个可能性是使用RoboVM。然而,它似乎只能在LinuxiOSMac OS X上运行。

截至今天,该项目仍然似乎有些活跃,与一些在线帖子声称该项目已死相反。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接