字节码相比本地代码有哪些优势?

41

似乎所有能够通过字节码实现的功能都可以在本地代码中更加轻松和快速地完成。理论上,您甚至可以通过在安装时将程序和库分发为字节码,然后编译为本地代码而不是JIT编译来保留平台和语言独立性。

那么一般情况下,什么情况下需要执行字节码而不是本地代码呢?

8个回答

33
转化,so this is not an issue in Java.)

  • Dynamic code loading: One of the most interesting features of Java is that it allows code to be loaded into a running program. You can have a program that starts with a small amount of functionality, and then downloads additional code as needed (for example, from a web site) to add new features or extend its capabilities. This is much more flexible than having to download a whole new version of the program every time you want to change something. The only downside to this capability is that it makes it more difficult to control what code is running on your system. (There are security mechanisms in place that try to prevent rogue code from being downloaded and run, but they are not foolproof.)


  • 算术运算,所以你不能编写Java代码来执行我们刚才描述的操作。但是,没有什么可以阻止某些人使用十六进制编辑器编写破坏性字节码,甚至构建Java字节码汇编程序。通常在执行之前分析程序的机器码并确定它是否做了任何坏事是不可能的。编写自修改代码之类的技巧意味着恶意操作甚至可能直到稍后才出现。但是Java字节码是为这种验证而设计的:它没有一个恶意程序员会使用来隐藏他们攻击的指令。
    在微处理器领域,RISC通常比CISC更可取。最好拥有一个小的指令集,并使用许多快速指令来完成工作,而不是将许多复杂操作实现为单个指令。 RISC设计需要在芯片上实现其指令的门数量更少,从而为管道和其他技术留出更多空间,使每个指令更快。然而,在解释器中,这些都不重要。如果您想为具有变量长度的switch语句实现一个单指令,该长度取决于case子句的数量,则没有理由不这样做。实际上,对于基于Web的语言而言,复杂的指令集是一个优势:这意味着相同的程序将更小(更复杂的指令较少),这意味着在受限制的网络上传输所需时间更短。
    因此,在考虑字节码与本机代码时,请考虑您要在可移植性,安全性,大小和执行速度之间做出哪些权衡。如果速度是唯一重要的因素,请使用本机代码。如果任何其他因素更重要,请使用字节码。我还要补充说,为每个发布版本维护一系列针对不同操作系统和架构的编译的相同代码库会变得非常乏味。使用相同的Java字节码在多个平台上运行并且“正常工作”是一个巨大的胜利。

    7
    四年后...可移植性:生成本机代码的编译器可以进行交叉编译,例如官方的 Go 编译器 gc,使得这一点变得非常简单。安全性:Native Client 在沙箱中运行本地代码,从而限制了其权限。尺寸:即使对于移动设备,如今大小也很少成为问题。 - Zippo
    3
    @Zippoxer 四年是怎么回事?交叉编译是一个非常古老的概念。但你仍然需要为每个平台单独编译代码。虚拟化也不是一个新概念,但将为本地执行编写的代码虚拟化并不同于将专门设计为在沙箱中运行的代码虚拟化。至于大小,我实际上根本不会称Java字节码为CISC。CIL也是如此。 - Malcolm

    16
    任何程序的性能都会因为编译、使用性能分析执行并将结果反馈到编译器进行第二遍编译而得以改善。实际使用的代码路径将被更加积极地优化,循环展开到恰当的程度,并安排热指令路径以最大化 I$ 命中率。
    这些都是好东西,但几乎从未被执行,因为构建二进制文件需要经历太多麻烦的步骤。
    这就是在编译成本地代码之前运行字节码的优势:性能分析信息自动可用。即时编译后的结果是高度优化的本地代码,适用于程序正在处理的特定数据。
    能够运行字节码还可以比静态编译器安全地使用更激进的本地优化。例如,如果一个函数的参数之一被标记为始终为空,那么该参数的所有处理可以直接从本地代码中省略。在函数序言中会对参数进行简短的有效性检查,如果该参数不为空,则 VM 会中止并返回字节码,重新开始性能分析。

    10

    字节码创建了一个额外的间接层。

    这个额外的间接层的优点包括:

    • 平台无关性
    • 可以创建任意数量的编程语言(语法),并将它们编译成相同的字节码。
    • 可以轻松创建跨语言转换器
    • x86、x64和IA64不再需要编译为单独的二进制文件。只需安装正确的虚拟机即可。
    • 每个操作系统只需创建一个虚拟机,就可以支持相同的程序。
    • 即时编译允许您仅通过替换单个修补源文件来更新程序。(对于网页非常有益)

    一些缺点:

    • 性能
    • 更容易反编译

    4
    所有答案都很好,但我的重点是性能。
    如果运行的代码花费大量时间调用库/系统例程 - 文件操作、数据库操作、发送Windows消息,那么即使它被JIT编译,也不会有太大影响,因为大部分时钟时间都是等待这些低级操作完成。
    然而,如果代码包含我们通常称之为“算法”的东西,这些东西必须快速且不花费太多时间调用函数,并且如果这些算法被频繁使用而成为性能问题,那么JIT非常重要。

    2
    我认为你已经回答了自己的问题:平台无关性。产生并分发到目标平台的是平台无关的字节码。在执行时,它会在执行开始之前或同时快速地编译成本机代码(即即时编译)。Java JVM和可能的.NET运行时都是按照这个原则操作的。

    2

    这里是Slashdot上关于IT技术的讨论!虽然有点过时,但评论非常好!


    1
    理想情况下,您应该拥有可移植的字节码,可以即时编译成本地代码。我认为,没有 JIT 的字节码解释器存在的原因主要是虚拟机添加本地代码编译会增加复杂性的实际事实。构建、调试和维护这个额外组件需要时间。并非每个人都有时间或资源来承担这种承诺。
    第二个因素是安全性。验证解释器不会崩溃比保证本地代码不会崩溃要容易得多。
    第三个因素是性能。对于只运行一次的小代码片段,生成机器代码通常需要更长的时间,而解释字节码则需要更短的时间。

    0

    与本地代码相比,字节码的可移植性和平台无关性可能是最显著的优点。


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