什么是便携性? java如何比其他语言更便携?

时间:2010-10-13 16:39:26

标签: java c programming-languages portability

我想知道Java如何比C,C ++和.NET以及任何其他语言更具可移植性。由于解释器和JVM,我已多次阅读过有关Java的可移植性,但JVM只是隐藏了硬件中的体系结构差异,对吧?对于不同的机器架构,我们仍然需要不同的JVM。我在这里错过了什么?因此,如果有人为最常见的体系结构为C编写抽象层,让我们说CVM,那么一旦安装了CVM,任何C程序都将在这些体系结构上运行,不是吗?

这种便携性究竟是什么? .NET可以称为可移植吗?

11 个答案:

答案 0 :(得分:40)

便携性不是黑白,是或否。可移植性是指我可以轻松地在一个人关心的所有平台上运行程序并运行它。

有一些事情会影响这一点。一个是语言本身。 Java语言规范通常留下更少的“实现”。例如,“i = i ++”在C和C ++中未定义,但在Java中具有已定义的含义。更实际地,类似“int”的类型在Java中具有特定大小(例如:int总是32位),而在C和C ++中,大小取决于平台和编译器。仅仅这些差异并不妨碍您在C和C ++中编写可移植代码,但您需要更加勤奋。

另一个是图书馆。 Java有一堆C和C ++没有的标准库。例如,线程,网络和GUI库。这些类型的库存在于C和C ++中,但它们不是标准的一部分,并且相应的库可以在不同平台之间变化很大。

最后,问题是你是否可以将可执行文件放在另一个平台上并让它在那里工作。这通常适用于Java,假设目标平台有一个JVM。 (并且人们关心的许多/大多数平台都有JVM)对于C和C ++,这通常是不正确的。你通常会去至少需要重新编译,而且假设你已经处理了前两点。

是的,如果存在多个平台的“CVM”,那将使C和C ++更具可移植性。您仍然需要以可移植的方式编写C代码(例如:假设除了标准所说的内容之外没有任何关于int的大小),或者您要写入CVM(假设它已做出统一的决定)所有目标平台上的所有这些事情)。您还需要放弃使用非标准库(无网络,线程或GUI)或为此目的写入CVM特定的库。那么我们并没有真正谈论使C和C ++更具可移植性,而是一种可移植的特殊CVM-C / C ++。

再一次,便携性不是黑白分明的事情。即使使用Java,仍然可能存在不兼容性。 GUI库(特别是AWT)因为具有不一致的行为而臭名昭着,而涉及线程的任何事情如果你变得粗鄙都会表现得不同。但是,一般来说,在一个平台上编写非平凡的Java程序并在另一个平台上运行它比使用C或C ++编写的程序执行相同操作要容易得多。

答案 1 :(得分:21)

正如其他人已经说过的那样,便携性在某种程度上是一个模糊概念。从某个角度来看,C实际上比Java更容易 更多 。 C对底层硬件做了很少的假设。它甚至不假设一个字节中有8位,或者负数应该用二进制补码表示。从理论上讲,只要你有一台基于Von Neumann的机器和编译器,你就可以选择C语言了。

事实上,用C语言编写的“Hello world”程序将在比用Java编写的“Hello world”程序更多的平台上运行。你可能会得到同样的“hello world”程序来处理PDP-11和iPhone。

然而,现实情况是,大多数真实世界的程序比输出“Hello world”做得更多。 Java因其实践而具有比C更具可移植性的声誉,将实际C程序移植到与现实Java程序不同的平台需要花费更多的精力。

这是因为C语言实际上是ANSI-C,这是一种非常通用的简单语言。它不支持网络编程,线程或GUI开发。因此,只要您编写包含任何这些内容的程序,就必须依赖于不太便携的扩展到C,如Win32或POSIX等等。

但是使用Java,网络编程,线程和GUI工具由语言定义并构建到每个VM实现中。

尽管如此,我认为很多程序员也低估了现代C / C ++在可移植性方面取得的进展。 POSIX在提供跨平台线程方面走得很远,而在C ++方面,Boost提供的网络和线程库基本上与Java中的任何东西一样可移植。这些库有一些特定于平台的怪癖,但Java也是如此。

本质上,Java依赖于具有VM实现的每个平台,该实现将以可预测的方式解释字节代码,并且C / C ++依赖于使用预处理器(#ifdef s)合并平台特定代码的库。这两种策略都允许跨平台线程,网络和GUI开发。简单来说,Java在可移植性方面取得了比C / C ++更快的进步。 Java语言规范几乎从第一天就开始进行线程化,网络化和GUI开发,而Boost网络库仅在2005年左右出现,直到2011年C ++ 11才开始在C ++中包含标准的可移植线程。

答案 2 :(得分:7)

编写Java程序时,它可以在为其编写JVM的所有平台上运行 - Windows,Linux,MacOS等。

如果您编写C ++程序,则必须专门为每个平台编译它。

现在,据说Java的座右铭“一次编写,随处运行”是一个神话。对于需要与许多本机资源进行交互的桌面应用程序来说,情况并非如此,但每个JavaEE应用程序都可以在任何平台上运行。目前我正在开发Windows,其他同事正在开发Linux - 没有任何问题。

(与可移植性相关的另一个问题是JavaEE(企业版)。据说使用JavaEE技术编写的应用程序可以在任何经过​​JavaEE认证的应用程序服务器中运行。但是,至少在JavaEE6之前是不行的。({{3 }}))

答案 3 :(得分:5)

可移植性是衡量一个程序在另一个环境上运行的努力程度,而不是它起源的程度。

现在你可以辩论一下Linux上的JVM是否与Windows上的环境不同(我认为是),但事实仍然是,在许多情况下,如果你要避免一些问题,就不会有任何努力。< / p>

您正在谈论的CVM非常类似于POSIX库和运行时库试图提供的内容,但是存在很大的实现差异,这使得跨越障碍很高。当然,就微软和苹果而言,这些可能是故意的,以防止开发人员在竞争平台上推出产品。

在.net方面,如果你能坚持使用mono提供的开源.Net实现,你将享受与Java大致相同的可移植性,但由于mono远远落后于Windows版本,所以这不是一个流行的选择。我不知道这对于基于服务器的开发有多受欢迎,我可以想象它不是一个问题。

答案 4 :(得分:3)

Java从开发人员的角度来看是可移植的:用Java编写的代码可以在任何环境中执行而无需重新编译。 C不可移植,因为在许多情况下它不仅与特定的操作系统相关联,而且在编译后也始终与特定的硬件架构相关联。 C ++也是如此。 .Net比C / C ++更便携,因为它也依赖于虚拟机,因此在编译时不依赖于特定的硬件架构,但它仅限于Windows机器(官方)。

你是对的,JVM是特定于平台的(它必须是!),但是当你说Java是可移植的时,你是从开发人员的角度谈论它而标准的Java开发人员不编写JVM,他们使用它: - )。

修改 @ Raze2Dust解决您的问题。是的,你可以。实际上,您可以通过编写生成机器代码而不是字节码的编译器来使Java平台特定。但正如其他一些评论所暗示的那样,你为什么要这样做呢?您必须创建一个解释器,以与JVM工作方式相同的方式将编译后的代码映射到操作。所以它的长短是绝对的,你绝对可以,但为什么会这样呢?

答案 5 :(得分:2)

你问是否可以写一个“C VM”。不完全是。 “Java”是Sun用来表示很多东西的重要术语,包括编程语言和虚拟机。 “C”只是一种编程语言:由编译器,操作系统和CPU来决定生成的二进制文件的格式。

C有时被认为是可移植的,因为它没有指定运行时。编写编译器的人能够选择对该平台有意义的东西。缺点是C足够低,并且平台不同,C程序在一个系统上工作正常而在另一个系统上根本不工作是很常见的。

如果将C语言与特定ABI结合使用,则可以为其定义VM,类似于JVM。有一些这样的事情,例如:

  • “英特尔二进制兼容性规范”就是这样一个ABI的例子(今天几乎没有人使用)
  • “Microsoft Windows”也可能是这样一个ABI(虽然是一个庞大且未被指定的版本),Wine是一个运行为其编写的程序的VM
  • “MS-DOS”,剂量μ为一个VM
  • “Linux”是当今比较流行的版本之一,其程序可以由Linux本身运行,NetBSDFreeBSD
  • “PA-RISC”,HP's Dynamo是类似JIT的VM

所有这些C VM实际上都是一台真正的机器 - 没有人,AFAIK,曾经制造过纯虚拟的C VM。这并不奇怪,因为C被设计为在硬件上高效运行,因此您可以在一个系统上正常运行。正如惠普所展示的那样,即使在同一平台上,您仍然可以使JIT更有效地运行代码。

答案 6 :(得分:2)

Java提供 三种 不同类型的可移植性:

源代码可移植性:无论底层CPU,操作系统或Java编译器如何,给定的Java程序都应产生相同的结果。

CPU架构可移植性:当前的Java编译器为尚不存在的CPU生成目标代码(称为字节码)。对于要在其上运行Java程序的每个真实CPU,Java解释器或虚拟机“执行”J代码。这个不存在的CPU允许相同的目标代码在任何存在Java解释器的CPU上运行。

OS / GUI可移植性:Java通过提供一组库函数(包含在Java提供的库中,例如awt,util和lang)来解决这个问题,这些函数与虚构的OS和虚构对话GUI。就像JVM提供虚拟CPU一样,Java库提供虚拟OS / GUI。每个Java实现都提供了实现此虚拟OS / GUI的库。使用这些库来提供所需操作系统和GUI功能的Java程序非常容易。

请参阅此link

答案 7 :(得分:1)

您需要针对不同体系结构的JVM,但当然您的Java程序在该JVM上运行 。因此,一旦您拥有了架构的JVM,那么您的Java程序就可用于该架构。

所以我可以编写一个Java程序,将其编译为Java字节码(与架构无关),这意味着我可以在任何架构上的任何JVM上运行它。 JVM抽象出底层架构,我的程序在虚拟机上运行。

答案 8 :(得分:1)

这个想法是Java 语言是可移植的(或者更准确地说,编译后的字节码是可移植的)。您是对的,每个VM都需要针对给定硬件配置文件的特定实现。但是,一旦完成了这项工作,所有 java字节码将在该平台上运行。你编写java / bytecode一次,它可以在任何JVM上运行。

.NET非常相似,但对原理的重视程度要低得多。 CLR类似于JVM,它有自己的字节码。单声道存在于* nix上,但你是正确的,它不是“官方的”。

答案 9 :(得分:1)

可移植性或维基百科中所写的Software Portability是跨多个环境(OS)重用相同软件(代码)的能力。 java JVM是一个可以在其设计用于的任何操作系统上运行的JVM:Windows,Linux,Mac OS等。

在.NET上,可以将软件移植到不同的平台。来自Wikipedia

  

.NET Framework的设计   从理论上讲它可以成为平台   不可知,因而跨平台   兼容。也就是说,编写了一个程序   使用框架应该运行   没有改变任何类型的系统   该框架是   实现。

由于Microsoft从未在Windows之外实现过.NET框架,并且认为.NET与平台无关,因此Mono可以运行.NET应用程序并编译代码以在Linux中运行。

对于诸如C ++,Pascal等语言,您必须转到每个操作系统并在该平台上构建它才能在该平台上运行它。 Windows中的EXE文件与linux中的.so(机器代码)不同,因为它们都使用不同的库与内核通信,每个操作系统都有自己的内核。

答案 10 :(得分:0)

WORE - 写一次到处运行

实际上,这仅限于具有JVM的平台,但这涵盖了您希望部署到的大多数平台。它几乎是解释语言和编译语言之间的一半,从而获得了两者的好处。