为什么我们需要/使用托管代码(而不是本机代码)
本文关键字:本机代码 托管代码 我们 为什么 | 更新日期: 2023-09-27 18:18:01
我遗漏了一些基本的东西。从源语言编译成字节码(java)或中间语言(.NET),然后在JVM或CLR内部运行它们有什么用?
使用托管代码会导致性能下降(或大或小),但好处是什么呢?我知道有垃圾收集和内存管理,但即使如此,不需要这个中间级别,直接将源代码编译为本机不是更好吗?
还有(我在这里添加了这个,因为它与问题直接相关)-显然Windows 10通用应用程序是用。net Native编译的,它编译为本机机器码。我很好奇为什么以前所有的。net程序都没有这样做。
除了在其他答案中指出的所有其他内容之外,这种方法的主要好处是在开发和维护中实现了重要的成本降低,并且大大提高了开发环境的可伸缩性。
考虑没有中间语言的情况;您需要为每种受支持的语言和每个受支持的平台开发和维护一个编译器。假设你有语言L1, L2和L3和平台P1, P2和P3。这意味着您需要开发和维护9个不同的编译器:C1(L1,P1)、C2(L1, P2)、C3(L1, P3)、C4(L2, P1)等等。
另一方面,使用中间公共语言I可以开发3个特定于语言的编译器C1(L1, I), C2(L2, I)和C3(L3, I)和3个特定于平台的编译器C4(I, P1), C5(I, P2)和C6(I, P3)。显然,支持的语言和平台基数越大,降低成本的效果就越显著。
在将来添加支持的平台或语言时,它还为您提供了很大的灵活性;任何新的语言L4将只需要开发一个单一的编译器C(L4, I),并且您立即以一次开发的价格支持所有平台。相反,如果你有一个新的平台P4,你只需要开发C(I, P4),然后,你有L1, L2和L3,它们都在P4中工作。
这基本上是一个双赢的局面。这是MSDN:
托管代码的好处
托管语言提供了一种通用的方法来处理内存管理和垃圾收集的细节,代价是少量的开销。这种权衡使您从容易出错的任务中解脱出来,并允许您编写更紧凑、可读和无错误的程序。非托管代码的好处
如果您使用非托管语言,例如c++,则必须编写额外的代码来管理内存和安全性,并在对象完成其目的后清理它们。内务管理细节是复杂的,并且与程序的预期功能无关,因此开发人员经常忽略这些任务,忽略它们,或者失去对它们的跟踪。因此,非托管代码的测试成本和时间往往更高,并且需要更多的程序员培训和纪律。
然而,开发人员通常更喜欢非托管代码,因为它执行更快,在指针的使用上更灵活,并且可以直接控制硬件。
字节码和JVM"诡计"意味着代码总是以相同的方式解释,与它运行的平台无关。我记得很久以前读到过Intel和AMD(以及其他处理器)的一些逻辑操作不同,这导致这些处理器上的结果不同,这可能导致一些跨平台错误。字节码解决了这个问题,结果总是不变的。
另一方面,如果你知道你只为一个平台编程,想要额外的性能,那就是嵌入式软件开发(或低级语言)的切入点。当您知道性能不是那么重要时,最好使用Java和。net。
这是因为编译为本机代码将使您的程序指定平台。但是,使用编译作为中间语言,您的程序是可移植的,并且如果有指定的JVM/CLR平台,则可以在每个平台上运行。
Java和。net都使用即时编译,因此它们可以提供可移植性,但与使用解释器相比,性能更好。
此外,微软已经与Visual Studio一起提供了Ngen,用于将。net代码编译为本机代码:
https://msdn.microsoft.com/en-us/library/6t9t5wcf (v = vs.110) . aspx
Ngen和。net Native之间的一个主要区别是Ngen仍然依赖于。net Framework,而。net Native将所需的。net代码与程序一起编译,因此不需要安装。net Framework。
在java中,当字节码生成时,这是特定于特定类型的体系结构,有助于java实现其"编译一次运行在任何地方"的能力。除此之外,它占用的内存非常少。