24

在这里看到除了 Java 之外还有很多在 JVM 上运行的语言。我对在 JVM 中运行的其他语言的整个概念有点困惑。所以:

为 JVM 提供其他语言有什么好处?

为 JVM 编写语言/编译器需要什么(高级术语)?

您如何在 JVM 中以一种语言(Java 除外)编写/编译/运行代码?


编辑:在接受的答案中回答了 3 个后续问题(最初是评论)。为了便于阅读,它们在这里重印:

使用 JPython 编写的应用程序如何与 Java 应用程序交互?

此外,该 JPython 应用程序可以使用任何 JDK 函数/对象吗?

如果它是 Jaskell 代码,它是一种函数式语言这一事实​​是否不会使其与 JDK 不兼容?

4

17 回答 17

33

分别解决您的三个问题:

为 JVM 提供其他语言有什么好处?

这里有两个因素。(1) 为什么 JVM 有 Java 以外的语言,以及 (2) 为什么在 JVM 上运行另一种语言,而不是不同的运行时?

  1. 其他语言可以满足其他需求。例如,Java 没有对闭包的内置支持,这个特性通常非常有用。
  2. 在 JVM 上运行的语言是与在 JVM 上运行的任何其他语言兼容的字节码,这意味着用一种语言编写的代码可以与用另一种语言编写的库进行交互。

为 JVM 编写语言/编译器需要什么(高级术语)?

JVM 读取字节码 (.class) 文件以获取它需要执行的指令。因此,任何要在 JVM 上运行的语言都需要编译为符合Sun 规范的字节码。此过程类似于编译为本机代码,不同之处在于不是编译为 CPU 可以理解的指令,而是将代码编译为 JVM 解释的指令。

您如何在 JVM 中以一种语言(Java 除外)编写/编译/运行代码?

与您在 Java 中编写/编译/运行代码的方式非常相似。为了让您的脚湿透,我建议您查看Scala,它可以在 JVM 上完美运行。

回答您的后续问题:

使用 JPython 编写的应用程序如何与 Java 应用程序交互?

这取决于实现选择弥合语言差距。在您的示例中,Jython 项目有一种直接的方法来执行此操作(请参见此处):

from java.net import URL
u = URL('http://jython.org')

此外,该 JPython 应用程序可以使用任何 JDK 函数/对象吗?

是的,见上文。

如果它是 Jaskell 代码,它是一种函数式语言这一事实​​是否不会使其与 JDK 不兼容?

不。例如,Scala(上面的链接)实现了功能特性,同时保持与 Java 的兼容性。例如:

object Timer {
  def oncePerSecond(callback: () => unit) {
    while (true) { callback(); Thread sleep 1000 }
  }
  def timeFlies() {
    println("time flies like an arrow...")
  }
  def main(args: Array[String]) {
    oncePerSecond(timeFlies)
  }
}
于 2008-09-17T18:35:31.453 回答
13

您在 JVM 上需要其他语言的原因与您通常需要多种编程语言的原因相同:不同的语言更适合解决不同的问题……静态类型与动态类型、严格与惰性……声明式、命令式、面向对象... ETC。

一般来说,为另一种语言编写一个“编译器”以在 JVM(或 .Net CLR)上运行,本质上是将这种语言编译成 java 字节码(或者在 .Net 的情况下,IL)而不是汇编/机器语言。

也就是说,为 JVM 编写的许多额外语言不是编译的,而是解释性脚本语言......

于 2008-09-17T16:37:16.573 回答
6

反过来,考虑一下您想要设计一种新语言,并且希望它在带有 JIT 和 GC 的托管运行时中运行。然后考虑你可以:

(a) 编写自己的托管运行时 (VM) 并解决各种技术难题,这些问题无疑会导致许多错误、性能不佳、线程不当和大量可移植性工作

或者

(b) 将你的语言编译成可以在 Java VM 上运行的字节码,Java VM 已经非常成熟、快速并且在许多平台上都受支持(有时有不止一种供应商实现选择)。

鉴于 JavaVM 字节码与 Java 语言的联系并不紧密,以至于过度限制了您可以实现的语言类型,因此它一直是希望在 VM 中运行的语言的流行目标环境。

于 2008-09-17T17:44:35.117 回答
4

Java 是一种相当冗长的编程语言,随着过去 5 年出现的所有新奇语言/框架,它很快就过时了。为了支持人们在语言中想要的所有花哨的语法并保持向后兼容性,向运行时添加更多语言更有意义。

另一个好处是它允许您在一个可能已经在许多公司生产的经过验证的托管平台上运行一些用 Ruby ala JRuby(又名 Rails)或 Grails(本质上是 Groovy on Railys)等编写的 Web 框架,而不必使用它几乎不像经过试验和测试的 Ruby 托管环境。

要编译其他语言,您只需将其转换为 Java 字节码。

于 2008-09-17T16:38:27.803 回答
3

我会回答,“因为Java 很烂”,但话又说回来,也许这太明显了…… ;-)

于 2008-09-17T16:35:18.390 回答
2

为 JVM 使用其他语言的优势与为计算机使用其他语言的优势大致相同:虽然所有图灵完备的语言在技术上都可以完成相同的任务,但某些语言使某些任务比其他语言更容易,而其他语言使其他任务更轻松。由于 JVM 是我们已经能够在所有(嗯,几乎所有)计算机上运行的东西,而且实际上已经有很多计算机,我们可以获得“一次编写,随处运行”的好处,但不需要那个使用Java。

为 JVM 编写语言/编译器与为真机编写语言/编译器并没有什么不同。真正的区别在于您必须编译为 JVM 的字节码而不是机器的可执行代码,但这在总体方案中确实是一个很小的区别。

在 JVM 中为 Java 以外的语言编写代码实际上与编写 Java 没有什么不同,当然,您将使用不同的语言。您将使用某人为其编写的编译器进行编译(同样,从根本上说,与 C 编译器没有太大区别,与 Java 编译器几乎没有什么不同),您最终将能够运行它就像您编译 Java 代码一样,因为一旦它在字节码中,JVM 就无法分辨它来自什么语言。

于 2008-09-17T16:39:47.490 回答
2

不同的语言适用于不同的任务。虽然某些问题域非常适合 Java 语言,但有些问题域更容易用替代语言表达。此外,对于习惯使用 Ruby、Python 等的用户来说,生成 Java 字节码并利用 JDK 类和 JIT 编译器的能力具有明显的优势。

于 2008-09-17T16:41:21.540 回答
2

只回答你的第二个问题:

JVM 只是一个抽象的机器和执行模型。因此,使用编译器定位它与编译器可能定位的任何其他机器和执行模型相同,无论是在硬件(x86、CELL 等)还是软件(parrot、.NET)中实现。JVM 相当简单,因此它实际上是编译器相当容易的目标。此外,实现往往具有非常好的 JIT 编译器(处理 javac 生成的糟糕代码),因此您可以获得良好的性能而不必担心很多优化。

有几点需要注意。首先,JVM 直接体现了 java 的模块和继承系统,因此尝试做任何其他事情(多重继承、多重分派)可能会很棘手,并且需要复杂的代码。其次,JVM 被优化以处理 javac 生成的那种字节码。生成与此完全不同的字节码可能会进入 JIT 编译器/JVM 的奇怪角落,这可能充其量是低效的(在最坏的情况下,它们可能会使 JVM 崩溃或至少给出虚假的 VirtualMachineError 异常)。

于 2008-09-17T16:54:47.560 回答
1

JVM 可以做什么是由 JVM 的字节码(您在 .class 文件中找到的)而不是源语言定义的。因此,更改高级源代码语言不会对可用功能产生重大影响。

至于为 JVM 编写编译器需要什么,您真正需要做的就是生成正确的字节码 / .class 文件。如何使用替代编译器编写/编译代码取决于所讨论的编译器,但是一旦编译器输出 .class 文件,运行它们与运行 javac 生成的 .class 文件没有什么不同。

于 2008-09-17T16:34:50.370 回答
1

这些其他语言的优势在于它们可以相对轻松地访问大量 java 库。

Java 人员的优势因语言而异——每个人都有一个故事告诉 Java 编码人员他们做得更好。有些人会强调如何使用它们将动态脚本添加到基于 JVM 的应用程序中,其他人只会谈论他们的语言如何更易于使用、具有更好的语法等等。

编写任何其他语言编译器所需的是相同的东西:解析为 AST,然后将其转换为目标架构的指令(字节码)并将其存储为正确的格式(.class 文件)。

从用户的角度来看,您只需编写代码并运行编译器二进制文件,就会生成 .class 文件,您可以将这些文件与您的 java 编译器生成的文件混合在一起。

于 2008-09-17T16:41:05.207 回答
1

.NET 语言更多的是为了展示而不是实际用处。每种语言都被如此屠杀,以至于它们都是带有新面孔的 C#。

为 Java VM 提供替代语言的原因有很多:

  • JVM 是多平台的。任何移植到 JVM 的语言都可以免费获得它。
  • 那里有相当多的遗留代码。ColdFusion 等过时的引擎性能更好,同时为客户提供了将他们的应用程序从传统解决方案缓慢过渡到现代解决方案的能力。
  • 某些形式的脚本更适合快速开发。例如,JavaFX 的设计考虑了快速图形开发。通过这种方式,它可以与 DarkBasic 等引擎竞争。(处理是这个领域的另一个参与者。)
  • 脚本环境可以提供控制。例如,应用程序可能希望向用户公开类似 VBA 的环境,而不公开底层 Java API。使用 Rhino 之类的引擎可以提供一个环境,在精心控制的沙箱中支持快速和肮脏的编码。
  • 解释脚本意味着不需要重新编译任何东西。无需重新编译转换为更动态的环境。例如,尽管 OpenOffice 将 Java 用作“脚本语言”,但 Java 在这种用途上很糟糕。用户必须经历各种重新编译/重新加载,这在 Javascript 等动态脚本环境中是不必要的。
  • 这让我想到了另一点。脚本引擎可以更容易地停止和重新加载,而无需停止和重新加载整个 JVM。这增加了脚本语言的实用性,因为可以随时重置环境。
于 2008-09-17T16:49:03.097 回答
1

编译器编写者生成 JVM 或 CLR 字节码要容易得多。与任何机器语言相比,它们是一种更清晰、更高级别的抽象。正因为如此,尝试创建新语言比以往任何时候都更加可行,因为您所要做的就是针对其中一个 VM 架构,并且您将拥有一组已经可用于您的语言的工具和库。它们让语言设计者更多地关注语言而不是所有必要的支持基础设施。

于 2008-09-17T17:38:45.770 回答
1

因为JSR进程正在渲染Java越来越死: http: //www.infoq.com/news/2009/01/java7-updated

遗憾的是,即使是像闭包这样重要且众所周知的添加,也只是因为成员无法就实现达成一致而没有添加。

于 2009-01-09T13:32:42.350 回答
1

Java 在七个主要版本(从 1.0 到 1.6)上积累了庞大的用户群。它的发展能力受到为生产中运行的数百万行 Java 代码保持向后兼容性的需要的限制。

这是一个问题,因为 Java 需要发展到:

  • 与从 Java 的成功和失败中学到的更新的编程语言竞争。
  • 结合编程语言设计的新进展。
  • 允许用户充分利用硬件的进步——例如多核处理器。
  • 修复一些引入意外问题的尖端想法(例如检查异常、泛型)。

向后兼容的要求是保持竞争力的障碍。

如果将 Java 与 C# 进行比较,Java 在成熟的、生产就绪的库和框架方面具有优势,而在语言特性和市场份额增长速度方面则处于劣势。这就是比较两种相隔一代的成功语言所期望的结果。

任何一种新语言都与 C# 相比 Java 在极端程度上具有相同的优势和劣势。在语言特性方面最大化优势并在成熟库和框架方面最小化劣势的一种方法是为现有虚拟机构建语言并使其与为该虚拟机编写的代码互操作。这就是 Groovy 和 Clojure 取得适度成功的原因。以及围绕 Scala 的兴奋。如果没有 JVM,这些语言只能在非常专业的细分市场中占据很小的一席之地,而有了 JVM,它们在主流中占据了重要的利基。

于 2010-07-02T08:18:23.070 回答
0

他们这样做是为了跟上 .Net 的步伐。.Net 允许 C#、VB、J#(以前)、F#、Python、Ruby(即将推出)和 c++。我可能错过了一些。对于脚本编写人员来说,其中最重要的可能是 Python。

于 2008-09-17T16:32:02.483 回答
0

在某种程度上,它可能是针对 .NET CLR 的“军备竞赛”。

但我认为将新语言引入 JVM 也有真正的原因,特别是当它们将“并行”运行时,您可以使用正确的语言来完成正确的工作,像 Groovy 这样的脚本语言可能正是您所需要的您的页面展示,而常规的旧 Java 更适合您的业务逻辑。

我将让更有资格的人来讨论编写新语言/编译器所需的内容。

至于怎么写代码,你照常在notepad/vi里写!(或者,如果您想以简单的方式进行,则使用支持该语言的开发工具。)编译将需要该语言的特殊编译器,该编译器将其解释并编译成字节码。

由于 java 在技术上也生成字节码,因此您无需执行任何特殊操作即可运行它。

于 2008-09-17T16:45:08.537 回答
0

原因是JVM平台提供了很多优势。

  • 数量庞大的图书馆
  • 更广泛的平台实施
  • 成熟的框架
  • 已成为基础架构一部分的遗留代码

Sun 试图通过其脚本规范支持的语言(例如 Python、Ruby)正在兴起,主要是由于它们感知到的生产力增强。从理论上讲,运行 Jython 可以让您更有效率,并利用Python的功能来解决更适合 Python 的问题,但仍然能够在运行时级别上与您现有的代码库集成。PythonRuby的经典实现对C库具有相同的功能。

此外,用动态语言表达某些东西通常比用 Java 更容易。如果是这种情况,你可以走另一条路;使用来自Java的Python/Ruby库。

性能会受到影响,但许多人愿意接受这一点,以换取更简洁、更清晰的代码库。

于 2009-01-09T13:57:29.413 回答