[英]How does C differ from Java's compilation model?
经典编译模型(C,C ++等)与Java编译模型之间的区别是什么?
你的问题的正确答案可能需要几百页回答,但我会尝试在几个段落中总结。
基本上,您所指的“经典编译模型”将人工编写的源代码作为输入,并发出机器代码,无需进一步翻译机器代码即可加载和运行。 其中一个结果是生成的机器代码只能在兼容的硬件上运行,并且只能在兼容的操作系统中运行。
Java编译模型将人工编写的源代码作为输入,并且不发出机器代码,而是发出所谓的“ 字节代码 ”。 字节代码不能直接在机器上执行。 相反,它需要由另一个编译器再次转换为机器代码,或者由在设备上执行与字节代码中的指令相对应的指令的设备即时解释。 后一种设备通常被称为虚拟机。 这种模型的一个分支是字节代码可以在任何具有字节码编译器或为其编写的虚拟机的平台上“运行”。 这为Java提供了完全可移植性的外观和效果,其中C ++编译器堆栈发出的机器代码不存在这种可移植性。
C(和C ++)编译模型有两个方面。 一个是它比Java更长的历史,这意味着它迎合了非常低功耗的编译器和机器。 第二个是编译目标 ,通常是低级机器代码。
要针对低内存编译器环境,C代码必须从上到下可读,没有回溯。 这意味着您必须严格遵守声明顺序。 (C ++为类定义放松了一点。)此外,每个源文件必须可编译为独立的翻译单元 ,不需要了解其他源文件。
其次,因为C以低级机器代码为目标,这意味着每个翻译单元基本上不包含元数据,与Java类文件形成鲜明对比。 这需要一个更强大的编码规则,其中必须为每个翻译单元提供必要的声明。 编译器不能只扫描所有其他文件以获取所需信息; 由用户提供。 (C ++更严格地强制执行此操作,在C中,您可以通过忘记声明来逃避令人讨厌的错误。)
请记住,C程序必须在编译时完全编译和链接,因此此时必须提供大量信息。 Java程序可以在运行时加载类,Java执行通常在运行时执行更多“拟合”操作(基本上,与C中的静态链接相反)。 Java的更复杂的运行时环境允许更灵活和模块化的编译模型。
我会勇敢地比较表现。 ;)
Java编译器javac
几乎不需要优化语法检查代码。 它执行所有必要的合理检查以确保它将在JVM上运行,并进行一些持续评估,就此而言。
大多数智能编译都是由JIT完成的,它可以根据程序的使用方式执行动态复杂化。 这允许它内联“虚拟”方法,例如,即使调用者和被调用者在不同的库中。
C / C ++编译器预先执行重要的静态分析。 这意味着程序将从一开始就以几乎全速运行。 CPU通过指令重新排序和分支预测执行一些动态优化。 虽然C / C ++缺乏动态优化,但它可以更轻松地对系统进行低级访问。 (它在Java中通常并非不可能,但在C / C ++中微不足道的低级操作在Java中可能很复杂和模糊)它还提供了更多方法来执行相同的操作,允许您选择最佳的问题解决方案。
当Java可能更快时。
当C / C ++可能更快。
基本上,有两种魔法。 只有某些巫师才能理解机器魔法。 JVM Bytecode魔法是通过一种特殊的向导来理解的,你必须雇用它才能使机器向导能够施放使你的计算机做事的法术。 C和C ++编译器通常发出机器类,而Java编译器发出JVM字节码 。
简而言之,“经典”编译(由材料提供的临时术语,因为它们没有真正的单词),基本上是针对真实设备(在我们的例子中是具有物理处理器的机器)进行编译。 相反,Java编译为针对虚拟设备的代码,虚拟设备是安装在计算机上的软件。 虚拟设备改变并瞄准真实机器。
通过这种方式,您的硬件就被抽象化了。 这就是Java可以在“任何”机器上工作的原因。
C / C ++在执行之前被编译。
Java在执行时被编译。
当然,两种语言都没有规定某种编译方式。
没有区别。 两者都将人类理解的源代码转换为某些机器理解的机器代码。 在Java的情况下,它以虚拟机为目标,即程序而不是硅片。
当然,没有什么可以阻止硅片理解JVM字节代码(在这种情况下,你可以将它从'字节代码'重命名为'机器代码')。 相反,没有什么可以阻止编译器将C / C ++代码转换为JVM字节代码。
两者都有一个运行时,都要求你告诉它你打算使用哪个运行时部分。
我真的认为你打算提出一个不同的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.