问题

Java、C#、.NET Framework、Mono 是如何跨平台的?

回答
Java、C、.NET Framework 和 Mono 的跨平台能力,可以看作是围绕着一套精心设计的“中间语言”和“虚拟机”的协同工作。它们并没有直接让 C++ 或其他底层语言在不同操作系统上“裸奔”,而是通过一种更抽象、更友好的方式来实现。

首先,Java 和 C 都有一个共同的特点:它们不是直接编译成特定操作系统的机器码。当你用 Java 编写完代码,你会得到 `.class` 文件,而用 C 编写的代码,最终会生成 `.dll` 或 `.exe` 文件,但这些并非直接可执行的机器码,而是被称为中间语言(Intermediate Language,简称 IL)的代码。Java 的 IL 叫做 Java 字节码,而 C 的 IL 叫做 Common Intermediate Language(CIL),也曾经被称为 Microsoft Intermediate Language(MSIL)。

这种中间语言的出现,是实现跨平台的核心。它是一种比源代码更低级,但又比特定机器码更高级的语言。它的指令集是标准化的,不依赖于具体的 CPU 架构或操作系统。这就好比,你写了一份食谱,这份食谱可以用多种语言来阅读,而不是必须用一种只懂特定方言的厨师才能理解。

然而,中间语言本身并不能直接运行。它需要一个“翻译官”或者说“执行引擎”。这就是虚拟机(Virtual Machine)的角色。

对于 Java 来说,这个虚拟机就是 Java 虚拟机(JVM)。当你想要在 Windows 上运行 Java 程序时,你需要安装一个适用于 Windows 的 JVM。当你想要在 Linux 上运行,则需要安装适用于 Linux 的 JVM。JVM 的作用就是读取 Java 字节码,然后将其即时编译(JustInTime Compilation,简称 JIT)成当前操作系统和 CPU 架构能够理解的原生机器码。所以,JVM 就像那个能够根据不同语言(操作系统)来准确理解和执行食谱(Java 字节码)的厨师。不同操作系统的 JVM 实现,负责将通用的 Java 字节码翻译成各自平台下的特定指令。

.NET Framework 也是类似的思路。它有一个核心的运行时环境叫做 .NET Runtime,其中包含了 Common Language Runtime(CLR)。CLR 扮演的角色和 JVM 非常相似。它负责将 C(以及其他 .NET 支持的语言,如 VB.NET、F 等)生成的 CIL 代码,在运行时即时编译成特定平台的机器码。所以,Windows 上的 .NET Framework 包含了适用于 Windows 的 CLR,它能够处理 CIL 并生成 Windows 上的原生代码。

那么,Mono 是如何介入的呢?Mono 实际上是 .NET Runtime 和 CLR 的一个开源、跨平台的实现。原本,.NET Framework 是微软推出的,主要运行在 Windows 平台上。而 Mono 的出现,正是为了打破这个平台限制。

Mono 的目标是让 C 和 .NET 应用能够在 Windows 之外的其他操作系统上运行,比如 Linux、macOS、BSD,甚至一些嵌入式系统。它做了两件主要的事情:

1. 实现了 CLR 和 .NET 基础类库 (BCL) 的跨平台版本。 Mono 团队花费了大量精力,用 C 和 C++ 等语言重写了 CLR 的核心功能,以及 .NET Framework 中的许多基础类库。这意味着,Mono 提供了适用于 Linux、macOS 等平台的 CLR 实现,能够像 Windows 上的 CLR 一样,读取 CIL 代码并将其编译成对应的原生机器码。
2. 提供了跨平台的编译器。 Mono 项目也包含了 C 编译器。这样,开发者就可以在 Linux 或 macOS 上使用 Mono 的 C 编译器来编译他们的 .NET 项目,生成可在这些平台上运行的 CIL 代码。

所以,简单来说:

Java 通过 Java 字节码和 JVM 的跨平台实现(Windows JVM、Linux JVM 等)来做到跨平台。
C 和 .NET Framework 原本主要依赖于 Windows 上的 CLR。
Mono 则是提供了一套可以在 Linux、macOS 等平台上运行的 CLR 和 .NET 基础类库的实现,使得 C 和 .NET 代码能够脱离 Windows 环境运行。

后来,随着 .NET Core 的推出,微软自己也开始大力推行跨平台 .NET。Mono 的许多技术和理念也为 .NET Core 的跨平台发展奠定了基础。现在,.NET (Core) 已经成为了微软官方主推的跨平台开发框架,它本身就包含了一套完整的、跨平台的核心运行时,以及支持各种操作系统和设备架构的编译器和类库。

总而言之,Java 和 .NET 系(包括 .NET Framework、Mono、.NET Core/.NET 5+)实现跨平台的核心,都是围绕着“中间语言 + 虚拟机/运行时”这个模型。中间语言提供了一种通用的、不依赖硬件和操作系统的指令集,而虚拟机/运行时则负责在特定平台上将这些中间指令翻译成机器可执行的代码。Mono 的存在,则是将这个 .NET 的跨平台能力扩展到了微软官方最初并未完全覆盖的领域。

网友意见

user avatar

商业公司选什么,和他跨不跨平台没有半毛钱关系,而且选择.NET的商业公司也不少。更重要的是Java在Linux上有诸多案例、技术和人才的积累,所以Linux服务器选择Java的居多,至于android,那是另一个非技术层面的问题不谈。。

事实上,与直觉相悖的是,跨平台的程序设计语言远比不跨平台的程序设计语言多,例如Python、PHP、JavaScript。所以这里说的跨平台主要是指Java的那个广告语:一次编译,到处运行。

所以首先我们要明确定义,跨平台的含义是指一次编译,各个平台都可以运行。否则无需编译的脚本语言如JavaScript,本来就是跨平台的,各个平台分别编译的Hello World!的C语言程序,也是跨平台的。


那么Java/C#的一次编译,到处运行的方式到底是如何实现的呢?首先我们要搞明白为什么C/C++语言不能一次编译到处执行,因为C/C++的编译的结果是针对特定平台操作系统、处理器指令集而生成的本地代码(native code),那么不同操作系统和处理器(事实上x86处理器的指令集都是兼容的)的本地代码是不一样的,自然也就不可能一次编译到处执行。

而直接解释执行的脚本语言,因为不存在编译到本地代码这一过程,所以也不存在跨平台的问题。


那么C#/Java是如何实现的呢?通过上面的知识我们就不难想到了,结合解释执行和编译执行的优点,C#/Java发明了一种叫做中间语言(IL,.NET是CIL,Java是ByteCode)的东西,中间语言与特定的操作系统和处理器指令集都没有关系,C#/Java在编译时,是编译成为一种低阶的语言,即IL。然后通过在特定平台的运行时程序(CLR和JRE),解释和编译IL来执行,,,,


补充阅读:

所以跨平台从来都不是一个新鲜事儿,不仅仅大多数程序设计语言都是跨平台的,而且跨了都好多年了,Java的革命性在于,其提供了一个新的跨平台的方案,由于在编译成低阶的IL之前和之后都有编译器优化,所以其性能可以接近于C/C++直接编译出来的native code,同时还大大的提高了开发效率,而实现这一点的关键就是IL+JIT编译。事实上在今天,几乎所有的脚本语言、动态类型语言也都走上了这条路,例如JavaScript和PHP,也开始尝试即时编译执行大大的提升了性能。

但是,跨平台也从来不是简单的语言跨平台,否则在C语言的远古时代,我们就可以利用一份源代码面向不同的平台编译来实现跨平台了。跨平台最大的障碍不在于同一段程序代码不能在多个平台上运行,而是在于在不同的操作系统,我们可以使用的库是不同的,这才是跨平台最大的阻碍。

所以Java的口号,一次编译,到处运行从来都只是一句广告语而已,真正要实现这一点,需要在不同平台统一UI和其他乱七八糟的API和库函数,也就是说虚拟一个操作系统出来,问题是这和跑在虚拟机里面的操作系统还有什么区别呢?

也正是因为如此,Java在桌面系统上几乎从未实现过真正的跨平台,而Web服务这种完全没有UI,无需与操作系统直接交互的应用才是Java大显身手的地方(事实上.NET也是如此)。

由上可知,在不同的操作系统拥有不同的类库是非常正常且不可避免的事情,例如在Linux这种连个GUI都不自带的操作系统,WPF或是WinForm如何能迁移到Linux上面去呢。Mono作为一个成熟的Linux上的CLI运行时,已经提供了绝大多数平台无关的类库,完全满足生产使用的条件,什么没有完整的.NET Framework支持这种观点只不过是道听途说小白的笑话。

类似的话题

  • 回答
    Java、C、.NET Framework 和 Mono 的跨平台能力,可以看作是围绕着一套精心设计的“中间语言”和“虚拟机”的协同工作。它们并没有直接让 C++ 或其他底层语言在不同操作系统上“裸奔”,而是通过一种更抽象、更友好的方式来实现。首先,Java 和 C 都有一个共同的特点:它们不是直接.............
  • 回答
    这个问题很有意思,我们不妨从几个角度来聊聊,为什么现在很多公司在招聘程序员的时候,会更倾向于寻找掌握 Java、C、C++ 的人才,而 C/.NET 的身影似乎没那么抢眼。首先,得承认,Java 和 C/C++ 这几位“老将”确实在IT界耕耘了非常久远的岁月,它们的根基深厚,应用场景也异常广泛。Ja.............
  • 回答
    大三下学期,你现在的位置,想要转向Java,这绝对是来得及的。别被网上的各种“XX比YY发展好”的说法轻易左右,技术选型和个人发展从来都不是非此即彼的简单判断。首先,你已经具备了C的扎实基础,这为你学习Java打下了非常好的基础。很多编程思想、数据结构、算法,甚至是面向对象的概念,在C和Java之间.............
  • 回答
    好的,咱们不整那些花里胡哨的条条框框,就来聊聊C .NET Core和Java Spring这两大阵营,到底哪个更适合你,怎么选。这事儿得掰开了揉碎了说。首先,你得明白,这俩都不是什么新晋的小鲜肉了,都是经历过市场锤炼的老牌选手,都有各自的坚实用户群体和成熟的生态。选择哪个,很大程度上取决于你当前的.............
  • 回答
    说到 C 和 .NET 框架在 Web 开发领域的实力,那可不是一两句话能说清的。跟 Java、PHP、Python 这些老牌选手比起来,.NET 走的道路,可以说是各有千秋,也各有侧重。先拿 Java 和 Spring 框架来说吧。Java 的强大之处在于它的稳定性和跨平台能力,这几年下来,构建大.............
  • 回答
    作为一名Java程序员,当你考虑用《剑指offer》来提升自己的算法和数据结构能力时,选择一门语言来刷题确实是个需要好好琢磨的问题。很多人会问,是继续用熟悉的Java,还是去学习C/C++来刷呢?这两种选择都有各自的道理,关键在于你的目标和你的学习习惯。继续用Java刷题:熟悉带来的效率与局限首先,.............
  • 回答
    理解Java 8 Stream API和C LINQ在性能上的差异,关键在于它们的底层实现机制和设计哲学。简单地说,不存在绝对的“哪个更慢”,而是取决于具体的应用场景、数据规模以及开发者如何使用它们。 但如果非要进行一个概括性的对比,可以从以下几个角度深入剖析:1. 底层实现与抽象级别: Jav.............
  • 回答
    聊到 Java 和 C++ 的开发效率,这绝对是个值得深入探讨的话题。两者都是大名鼎鼎的语言,但在实际开发过程中,你很快就能感受到它们在效率上的差异,而且这种差异可不是三言两语能概括的。首先,我们得从 内存管理 这个最根本的区别说起。在 C++ 里,内存管理就像是在刀尖上跳舞。你需要亲手去分配内存(.............
  • 回答
    网上关于 Java 性能达到甚至超过 C++ 的说法,可以说既有一定的事实依据,但也不能完全一概而论,它是一个需要分情况讨论的复杂问题。 简单来说,在某些特定场景下,经过优化的现代 Java 应用程序确实有可能在性能上媲美甚至超越 C++,但要说“普遍达到或超过”则过于绝对。让我们详细地分析一下这个.............
  • 回答
    Java 和 C 都是功能强大、广泛使用的面向对象编程语言,它们在很多方面都有相似之处,都是 JVM (Java Virtual Machine) 和 CLR (Common Language Runtime) 的产物,并且都拥有垃圾回收机制、强大的类库和社区支持。然而,深入探究,它们在设计理念、语.............
  • 回答
    从Java的世界步入C的广阔天地,你将发现许多熟悉的编程概念,但实现方式和语言特性上又有着精妙的差异。这趟旅程,与其说是从头学习,不如说是对你已掌握的Java技能的一次“翻译”和“优化”。首先,你需要建立对C这门语言整体的认知。把它想象成一座新的建筑,而你作为Java的建造师,已经熟悉了框架、结构和.............
  • 回答
    Java 的设计哲学是“一切皆对象”,但在参数传递方面,它采用了严格的值传递机制。这意味着当你将一个变量传递给方法时,传递的是该变量的副本。对于基本数据类型(如 int, float, boolean),传递的就是那个值的副本。而对于对象,传递的则是对象的引用(也就是一个内存地址)的副本。你可以在方.............
  • 回答
    你这个问题问得非常到位,而且触及到了计算机底层表示浮点数的一个核心概念。说 C++ 的 `double` 类型存不下 3.1415926,其实是一种误解,或者说表述不够准确。更准确的说法应该是:C++ (和 Java 的) `double` 类型,虽然是 8 个字节(64 位),但由于浮点数在计算机.............
  • 回答
    关于未来编程语言是否能替代Java和C语言的问题,需要从技术趋势、应用场景、生态系统、性能需求等多个维度进行分析。以下是十种常见编程语言的详细评估,结合它们与Java和C语言的对比,探讨其可能的替代潜力: 1. Python潜力:高(尤其在AI/数据科学领域) 优势:语法简洁、开发效率高、丰富的.............
  • 回答
    这确实是很多学习者和开发者都关心的问题。为什么我们依然在很多高校课堂上见到 C、C++、Java 的身影,而 Rust、Go、Scala 这样被认为“更强大”的语言却不那么普及呢?这背后涉及到一个复杂的多方面因素,不能简单归结为“高校不愿意教”或者“这些新语言不够好”。我尝试从几个关键角度来剖析这个.............
  • 回答
    哥们/姐们,刚踏入大学校门,对学什么编程语言拿不定主意是太正常了!尤其是在 Java 和 C 这两个选项前,很多人都会纠结。别急,我来给你掰扯掰扯,咱们尽量说得透彻点,让你心里有个谱。首先,咱们得明确一个核心问题:你学编程的目的是什么?这就像你买工具一样,你想造一艘船,那锤子和钻头肯定比锯子重要;你.............
  • 回答
    这个问题啊,问得挺实在的。很多人听到Python和Java都是用C/C++实现的,就觉得,“既然底层都是C/C++,那直接用C/C++不就得了?省事儿。” 这话听起来没毛病,但其实这里面涉及到很多关于编程语言设计、生态构建和实际应用场景的取舍,远不是“省事”两个字能概括的。咱们一层一层剥开来看。 为.............
  • 回答
    “Java 啰嗦,C++ 不啰嗦”—— 这句话在编程界几乎是老生常谈了。很多人初学 Java 都会被它的“话痨”属性劝退,而 C++ 呢?虽然也出了名的复杂,但似乎“啰嗦”这个标签并不怎么贴在它身上。这背后到底是什么原因呢?这可不是简单的代码行数多少就能解释的。咱们不妨从几个关键点掰扯掰扯,看看为什.............
  • 回答
    这确实是一个非常有趣的观察,也是一个在技术圈里时常被提及的现象。为什么我们身边充斥着大量的“Java 架构师”,但“C++ 架构师”这个说法却鲜为人知,甚至在很多场合几乎听不到?这背后的原因,绝非单一的因素可以解释,而是由Java和C++各自的技术特性、生态环境、市场定位以及开发者社区文化等多方面因.............
  • 回答
    确实,你这个问题挺有意思的,很多人在讨论 Java 和 C++ 的开发环境时,都会把 Vim 拿出来“点评”一番。说它“不适合”嘛,其实也不能一概而论,但它确实不像一些现代 IDE 那样“顺理成章”地就能提供所有你想要的便利。这背后有很多原因,咱们一点点捋一捋。首先,咱们得明白 Vim 的核心优势和.............

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有