是什么使JVM如此通用以支持许多JVM语言?


18

JVM支持Java以外的许多语言,如Groovy,Clojure,Scala等,这是Java不同的函数式语言(我指的是Java版本8之前,其中Lambda's不支持)不支持的功能capabilities.On高水平是什么让JVM如此多才多艺,它可以支持面向对象语言和功能语言吗?


“具有功能的Groovy,Clojure,Scala等”。其中一些功能比其他功能更强大。我将使用Groovy功能最少,Clojure最多,Scala居中的秤。
Vorg van Geir

Answers:


37

与其他VM相比,JVM实际上并不是特别通用。它直接支持静态类型的OO。对于其他所有内容,您必须查看可以使用的部分以及如何在这些部分之上构建语言需要的其他所有内容。

例如,在Java 7引入invokedynamic字节码之前,很难在JVM上实现动态类型的OO语言-您必须使用不利于性能的复杂变通方法,并导致令人肿的堆栈跟踪。

但是,在此之前,在JVM上实现了一堆动态语言(Groovy,Jython,JRuby等)。

不是因为JVM如此通用,而是因为它是如此广泛,并且因为它具有非常成熟,得到良好支持和高性能的实现。

而且,也许甚至更重要,因为那里有大量的Java代码几乎可以做任何事情,而且如果您的语言在JVM上运行,则可以轻松地提供与该代码集成的功能。基本上,在JVM上运行您的语言是21世纪提供与C互操作性的版本。


好答案(+1)。您提到的最后一点是恕我直言,这也是Java作为一种语言的流行的原因:最后,拥有大量可以免费重用的代码比使用最新和最流行的语言可节省更多时间。特征。
Giorgio

4

编写JVM基本上是像CPU一样,其中有一组指令(类似于汇编),VM可以运行字节码。如果您可以编写生成有效字节码集的编译器,那么JVM可以运行它们。

维基百科列出了字节码:

http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings

以及有关JVM如何加载字节码的说明:

http://en.wikipedia.org/wiki/Java_virtual_machine

通过使用invoke样式字节码,功能语言可以执行代码,而无论源是什么样。另外,除了invokevirtual,jruby之类的语言实现也​​为它们的运行方式提供了一定的灵活性。


1
对于其他所有虚拟机,也是如此:YARV Ruby虚拟机,Rubinius Ruby虚拟机,CPython VM(毕竟比JVM早),Parrot,各种Smalltalk和Lisp VM,当然还有Pascal P-代码系统,之后对JVM进行建模。
约尔格W¯¯米塔格

同意,JVM绝对不是第一个出现的VM。我认为JVM在其他语言中也很流行,因为Java很流行,VM也在积极开发中并有据可查。
萨斯伯里

2

我还要补充一点,JVM支持定义良好且相当不错的内存模型(JMM),这意味着对一致(尽管是低级)线程行为的良好支持。它还具有功能强大的即时编译器(由于使用了MethodHandles和invokedynamic,它对动态语言不再有用)。

最后但并非最不重要的是JVM的Garbage Collection子系统,子系统(通过适当的调整)可以为您管理内存,而不管顶部的语言是什么。


JMM是我最不喜欢Java的东西之一。我是有效不可变数据的支持者(例如,其内容在其他线程可见之后永远不会改变的数组),但是给出了这样someField = new int[]{42};的声明,如确保所有看到新数组的线程都能看到值的唯一方法42要么做田野final要么volatile。如果该字段是懒散生成的,但经常访问,则使其final无法正常工作,并且volatile每次访问该字段都会造成不必要的同步损失。在最宽松的.NET模型中……
supercat

...代码可以要求数组的填充发生在引用存储之前。其他读取该字段的线程可能会或可能不会看到对新数组的引用,但是他们自己将不付出任何代价,即如果他们看到新数组,便会看到其内容。
2015年

1

其中的关键元素是编译与执行阶段的分离。这样,可以编写将其他语言编译为字节码的其他编译器。

字节码的行为类似于CPU的机器码-您具有运行程序所需的所有小操作-您可以获取变量,对其进行数学运算,进行条件运算等。

Java也并不特殊。在Java中,与其他VM不同,存在多种语言甚至不是设计目标。对于Microsoft的.Net CIL,运行多种语言(C#,VB.Net等)的能力是关键的设计元素,Perl6项目中的ParrotVM也旨在成为通用VM。

出于乐趣,我曾经创建了一个证明,甚至PHP的Zend Engine也允许这样做。

坦率地说,这并不是什么新鲜事物-即使在真正的硬件上,您也可以运行多种语言-例如C或Fortran。

与编译和执行分离的区别在于,它们是clssic解释器,例如某些形式的Basic,shell脚本等。它们的工作方式通常是或多或少逐行执行代码,而没有立即采用这种形式在两者之间。


1

JVM是我所知道的第一个虚拟机,它结合了垃圾收集,性能和可行的沙箱模型。支持JVM的许多语言的出现可能并不是其“多功能性”的结果,而是Java语言缺乏人们在编程语言中想要的一些重要功能这一事实。例如,虽然大多数机器语言只有大约六种数据类型(例如字节,半字,字,双字,单精度浮点数和双精度浮点数),但绝大多数编程语言都允许代码使用任意数量的用户定义数据类型。JVM可以识别一些与典型计算机上相似的原始类型,还有另外一种类型:混杂对象引用。Java语言同样可以识别这些原语,和混杂对象引用。尽管可能会限制变量不包含对非特定类的任何内容的引用,但该语言在以下类型的任何类型的字段之间没有区别List<String>可能由实例MyThing类持有MyClass

  • 对某些代码的引用被认为是的不可变实现 List<String>

  • 对可变列表类型的实例的引用,该实例永远不会暴露于任何可能对其进行变异的对象。

  • 对可变列表的引用,除了在执行MyThings的方法期间外,在Universe的任何地方都不可能存在其他引用。

  • 其他对象拥有的可变列表的引用,该其他对象希望MyThing以某种方式使用该可变对象。

  • MyThing拥有的可变列表的引用,但该可变列表也已暴露给其他一些对象,以便他们可以对其进行某些操作。

即使所有这些字段都可以具有type List<String>,但它们持有非常不同的东西。一种表达性的语言可能允许区分这些含义,但是Java不允许。由于一种语言可以将含义附加到此类事物上(至少在通用上下文之外)并且可以在JVM上运行,因此,以JVM为目标的语言为Java不能表达的概念留出了很大的空间。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.