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

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

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

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

有一些事情会影响这一点。 一个是语言本身。 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 ++编写的程序中执行相同操作要容易得多。

正如其他人已经说过的那样,便携性在某种程度上是一个模糊概念。 从某个角度来看,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 ++中包含标准的可移植线程。

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

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

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

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

可移植性是衡量程序在另一个环境上运行的工作量的量度。

现在你可以讨论Linux上的JVM是否与Windows不同(我认为是),但事实仍然是,在许多情况下,如果你要避免一些陷阱,就不会有任何努力。

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

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

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

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

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

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

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

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

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

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

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的库。 使用这些库来提供所需操作系统和GUIfunction的Java程序非常容易。

看到这个链接

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

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

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

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

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

在.NET上,可以将软件移植到不同的平台。 来自维基百科 :

.NET Framework的设计允许它在理论上与平台无关,因此跨平台兼容。 也就是说,编写使用框架的程序应该在没有实现框架实现的任何类型系统的情况下运行。

而且由于Microsoft从未在Windows之外实现.NET框架并且看到.NET与平台无关,因此Mono使得运行.NET应用程序和编译代码成为可能在Linux中运行。

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

好的 – 写一次到处运行

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