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