为什么我们 need/use 托管代码(超过本机代码)?

Why do we need/use managed code (over native)?

我在这里遗漏了一些基本的东西。从源语言编译成字节码 (java) 或中间语言 (.NET),然后 运行 从 JVM 或 CLR 内部编译它们有什么用?


使用托管代码会降低性能(无论大小),但好处是什么?我知道有垃圾收集和内存管理,但即便如此,直接将源代码编译为本机版本而不需要这个中间级别不是更好吗?

此外(我在此处添加它,因为它与问题直接相关)- 显然 Windows 10 个通用应用程序是使用 .NET Native 编译的,可编译为本机代码。我很好奇为什么以前没有对所有 .NET 程序都这样做。

字节码和 JVM "shenanigans" 意味着代码总是以相同的方式解释,独立于它所在的平台 运行。我记得很久以前模糊地读到 Intel 和 AMD(以及其他处理器)以不同的方式执行一些逻辑操作,这导致这些处理器上的结果不同,并且可能导致一些跨平台错误。所以字节码解决了这个问题,结果总是不变的。

另一方面,如果您知道您只为一个平台编程并且想要额外的性能,那么嵌入式软件开发(或低级语言)就可以派上用场。Java 和 .NET 是当您知道性能不是那么重要时最好使用。

这是因为编译为本机代码会指定您的程序平台。 但是,通过编译为中间语言,如果有指定的 JVM / CLR 平台,您的程序是可移植的并且可以 运行 在每个平台上。

Java 和 .Net 都使用即时编译,因此它们可以提供可移植性,但与使用解释器相比仍然具有更好的性能。

此外,Microsoft 已经提供了 Ngen 和 Visual Studio 用于将 .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实现其'compile once run anywhere'能力。 除此之外,它占用的内存非常少。

这是来自MSDN:

托管代码的好处

托管语言提供了一种通用方法来处理内存管理和垃圾收集的细节,但代价是少量的开销。这种权衡使您从容易出错的任务中解放出来,并允许您编写更紧凑、可读且无错误的程序。

非托管代码的好处

如果您使用非托管语言(例如 C++),则必须编写额外的代码来管理内存和安全性,并在对象达到其目的后清理它们。内务处理的细节很复杂,并且与程序的预期功能无关,所以开发人员经常忽视这些任务,忽视它们,或者忘记它们。因此,非托管代码的测试成本和时间往往更高,并且需要更多的程序员培训和纪律。

但是,开发人员通常更喜欢非托管代码,因为它执行速度更快,允许更灵活地使用指针,并提供对硬件的直接控制。

除了其他答案中指出的所有其他内容之外,这种方法的主要好处是在开发和维护方面实现了重要的成本降低以及开发环境的可扩展性得到了极大的改善。

考虑没有中间语言的情况;您需要为每种支持的语言 每个支持的平台开发和维护一个编译器。假设您有语言 L1L2L3 以及平台 P1P2P3。这意味着您需要开发和维护 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) 然后,宾果游戏,你有 L1L2L3 都在 P4.

这基本上是一个双赢的局面。