Java中字节码的目的是什么?

13

假设我可以在几秒钟内编译300个类,那么Java的实现就可以直接使用Java源文件而不是字节码作为输入,然后编译并缓存输入的源代码,并且永远不会再次编译它(例如Python就是这样做的,许多语言实现也是如此,甚至不必费心缓存):

  1. 这个初始编译体验将等同于用户已经习惯的安装过程。
  2. 这将消除在字节码解释器中实现verification(实际上只是重新实现了部分编译时检查)的非常规任务,从而减少实现复杂性。
  3. 目前的Java会在每次启动时验证输入的字节码,即使它之前已经验证过了。第2点当然会减少启动时间,因为它消除了这一步骤(尽管当前的Java平台也可以在某个地方缓存“checked”状态以减少启动时间,我不确定它是否这样做)。
  4. 这将允许实现按照他们想要的方式进行编译(或者根本不编译),例如用于提高性能。Android甚至不使用Java字节码,它使用dalvik字节码,因为他们声称它更适合他们的需求(例如在他们的硬件上更有效)。如果没有字节码,Google做出的这个设计决策将完全透明。
  5. 这将促进开源

解释了为什么要分发字节码而不是本地代码,但要明确的是,我想知道为什么需要编译后的格式进行分发?假设编译很重要,为什么不让运行时编译源代码并缓存它呢?

我能想到的唯一剩下的理由是为了混淆,但是...

  • 当前编译器编译的方式使得代码可以被机械化地准确反编译
  • 源代码也可以被混淆

...所以这一点被简化为直觉认为字节码比源代码更复杂,因此有一个字节码分发格式可以欺骗商人认为他们的知识产权受到保护(即字节码将“增加价值”,但没有技术原因)。

为什么Java平台设计为向用户分发字节码,而不是源代码?我在互联网上找不到任何解释。我是否漏掉了什么重要的原因?


如果你提出了一个理由,你应该明确它是语言设计者最初拥有的理由还是今天仍然有效的理由。

1个回答

5
你只是在你的小世界里思考。有一些令人信服的理由来编译源代码并交付字节码:
  • 下载时间(小程序应成为广泛接受的Web技术)- 用户不需要源代码,那么为什么要保留源代码?减少传输的信息量意味着更快的下载速度。
  • 减少启动时间。每次运行时编译需要额外的时间。如果您可以每秒编译300个类,那么现在单独JRE的启动时间将增加5-10秒。而且1995年的机器速度还比较慢,你知道的。
  • Java旨在面向多种平台。有些平台不像您的PC那样强大。想想嵌入式和移动设备。它们可能没有存储空间或能力来编译代码。
  • 字节码允许任何语言编译为字节码 - 不仅限于Java。有很多其他语言可以编译为字节码。你会喜欢为它们中的每一个安装一个新的编译器吗?
  • 公司通常不愿意将“源代码”交出手中。如果程序以“源代码”的形式交付,则Java将面临更多的接受问题。
  • 字节码是一种足够简单的机器码形式,可以直接在硬件中执行(有一些嵌入式设计具有部分本地字节码支持)。
我相信还有更多关于字节码的优点我还没有考虑到。

3
优点和缺点:"减少启动时间。每次运行编译需要额外的时间。" 你没有完全阅读问题:@Dog明确提出了一个缓存机制来解决这个问题,并且还减少了启动时间,因为没有字节码验证。你关于“字节码作为汇编语言”的观点是无效和特别情况,因为它最初并不是用于编译其他语言,并且已被证明在某些其他语言中非常糟糕。编译为JavaScript同样有效。 - Harold R. Eason
2
字节码与压缩源代码的大小差异微不足道。但是 Dalvik 的存在证明了最后一个观点是错误的。IP 和在小设备上运行的点是我考虑的要点... - Dog
除非有修改,否则最后一点是“字节码是一种足够简单以直接在硬件中执行的机器码形式”,我不认为这被Android所证明是错误的。Android设备不执行JVM或Dalvik字节码,但不是因为它们不能,而是出于其他原因。 - user395760
@HaroldR.Eason 他在第二点明确表示源代码将被验证,而不是编译(也许意图是暗示,但并不清楚)。他从未说过他想要存储已编译的代码在哪里/是否存储,事实上他在第四点中暗示编译模式可以更改。可以有两种理解方式。 - Durandal
@delnan:一些ARMv5TE微控制器包括硬件模式(“Jazelle”),可以直接处理大多数JVM指令(请参见Durandel的“Jazelle”链接)。尽管这种能力的实际用途远不如预期(即使有硬件支持,执行JVM直接代码的速度也比运行JITted代码慢),但允许硬件执行的愿望很容易影响JVM的设计。 - supercat
显示剩余2条评论

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