看起来你可以用字节码做的任何事情都可以在本机代码中轻松快捷地完成。理论上,您甚至可以通过以字节码分发程序和库,然后在安装时编译为本机代码,而不是 JIT 来保持平台和语言的独立性。
所以一般来说,你什么时候想执行字节码而不是原生的?
SGI 的 Hank Shiffman 说(很久以前,但这是真的):
Java使用字节码而不是去系统的本机代码有三个优点:
可移植性: 每种计算机都有其独特的指令集。虽然一些处理器包含了它们前辈的指令,但通常情况下,在一种计算机上运行的程序不会在任何其他计算机上运行。添加操作系统提供的服务,每个系统都以自己独特的方式描述这些服务,您就会遇到兼容性问题。一般来说,你不能为一种系统编写和编译程序并在没有大量工作的情况下在任何其他系统上运行它。Java 通过在应用程序和真实环境(计算机 + 操作系统)之间插入其虚拟机来绕过这个限制。如果应用程序被编译为 Java 字节码,并且该字节码在每个环境中都以相同的方式解释,那么您可以编写一个程序,该程序将在支持 Java 的所有不同平台上运行。(无论如何,这就是理论。在实践中,总会有一些小的不兼容性等待程序员。)
安全:Java 的优点之一是它与 Web 的集成。将使用 Java 的网页加载到浏览器中,Java 代码会自动下载并执行。但是,如果代码破坏了文件,无论是出于恶意还是程序员的草率,怎么办?Java 通过禁止潜在的危险操作来防止下载的小程序做任何破坏性的事情。在它允许代码运行之前,它会检查它是否试图绕过安全性。它验证数据的使用是否一致:在某个阶段将数据项作为整数操作,然后稍后尝试将其用作指针的代码将被捕获并阻止执行。(Java 语言不允许指针运算,因此您不能编写 Java 代码来执行我们刚刚描述的操作。但是,没有什么可以阻止某人使用十六进制编辑器自己编写破坏性字节码,甚至构建 Java 字节码汇编器。)通常不可能在执行之前分析程序的机器码并确定它是否做错了什么。像编写自修改代码这样的技巧意味着邪恶的操作甚至可能在以后才存在。但是 Java 字节码是为这种验证而设计的:它没有恶意程序员用来隐藏攻击的指令。像编写自修改代码这样的技巧意味着邪恶的操作甚至可能在以后才存在。但是 Java 字节码是为这种验证而设计的:它没有恶意程序员用来隐藏攻击的指令。像编写自修改代码这样的技巧意味着邪恶的操作甚至可能在以后才存在。但是 Java 字节码是为这种验证而设计的:它没有恶意程序员用来隐藏攻击的指令。
尺寸:在微处理器世界中,RISC 通常优于 CISC。最好有一个小的指令集并使用许多快速指令来完成一项工作,而不是将许多复杂的操作实现为单个指令。RISC 设计需要更少的芯片上的门来实现它们的指令,从而为流水线和其他技术留出更多空间,以使每条指令更快。然而,在口译员中,这些都不重要。如果您想根据 case 子句的数量为 switch 语句实现一条可变长度的指令,那么没有理由不这样做。事实上,复杂的指令集对于基于 Web 的语言来说是一个优势:这意味着相同的程序会更小(指令越少越复杂),
因此,在考虑字节码与原生代码时,请考虑您希望在可移植性、安全性、大小和执行速度之间做出哪些权衡。如果速度是唯一重要的因素,那就选择原生。如果其他任何一个更重要,请使用字节码。
我还要补充一点,为每个版本维护一系列针对相同代码库的操作系统和体系结构的编译可能会变得非常乏味。在多个平台上使用相同的 Java 字节码并让它“正常工作”是一个巨大的胜利。
基本上任何程序的性能都会提高,如果它被编译,执行分析,并将结果反馈给编译器进行第二次传递。实际使用的代码路径将被更积极地优化,循环展开到完全正确的程度,并且热指令路径被安排以最大化 I$ 命中。
所有的好东西,但它几乎从来没有完成,因为通过这么多步骤来构建二进制文件很烦人。
这是在将字节码编译为本机代码之前运行一段时间的优势:分析信息是自动可用的。即时编译后的结果是针对程序正在处理的特定数据高度优化的本机代码。
能够运行字节码还可以实现比静态编译器安全使用的更积极的本机优化。例如,如果函数的参数之一被记录为始终为 NULL,则可以简单地从本机代码中省略对该参数的所有处理。将对函数序言中的参数进行简短的有效性检查,如果该参数不为 NULL,VM 将中止返回字节码并再次开始分析。
字节码创建了一个额外的间接级别。
这种额外的间接级别的优点是:
一些缺点:
所有好的答案,但我的热键已被击中 - 性能。
如果正在运行的代码将所有时间都花在调用库/系统例程上——文件操作、数据库操作、发送 Windows 消息,那么它是否被 JITted 并不重要,因为大部分时钟时间都花在等待那些较低的 -水平操作来完成。
但是,如果代码中包含我们通常称为“算法”的东西,它们必须快速且不花费太多时间调用函数,并且如果这些东西的使用频率足够高而成为性能问题,那么 JIT 就非常重要。
我认为您刚刚回答了自己的问题:平台独立性。生成独立于平台的字节码并将其分发到其目标平台。执行时,它会在执行开始之前或同时(即时)快速编译为本机代码。Java JVM 和大概的 .NET 运行时都是按照这个原则运行的。
这里:http ://slashdot.org/developers/02/01/31/013247.shtml
去看看 Slashdot 的极客们是怎么说的吧!有点过时,但非常好的评论!
理想情况下,您将拥有可移植的字节码,可将 Just In Time 编译为本机代码。我认为字节码解释器在没有 JIT 的情况下存在的原因主要是由于本机代码编译增加了虚拟机的复杂性这一实际事实。构建、调试和维护该附加组件需要时间。不是每个人都有时间或资源做出这样的承诺。
第二个因素是安全性。验证解释器不会崩溃比保证本机代码相同要容易得多。
三是性能。生成机器代码通常比为只运行一次的小段代码解释字节码要花费更多时间。
可移植性和平台独立性可能是字节码相对于本机代码最显着的优势。