多くのJVM言語をサポートするために、JVMが非常に多用途なのはなぜですか?


18

以下のようなJava以外の多くの言語ので、JVMがサポートGroovy,Clojure,ScalaするJavaとは異なり、関数型言語ですなど(私が言及していますバージョン8以前のJavaLambda'sそれほど多彩な機能capabilities.OnにJVMを作るもの高いレベルをサポートしていませんサポートされていません)オブジェクト指向言語と関数型言語の両方をサポートできますか?


「機能的なグルーヴィー、クロージャー、スカラなど」。それらのいくつかは他のものよりも機能的です。スケールは、Groovyが最も機能が少なく、Clojureが最も大きく、Scalaが中央にあります。
ヴォルグヴァンガイア

回答:


37

他のVMと比較して、JVMは実際には特に汎用性がありません。静的に型指定されたオブジェクト指向を直接サポートします。他のすべてについては、使用できる部分と、それらの部分の上に言語が必要とする他のすべてを構築する方法を確認する必要があります。

たとえば、Java 7がinvokedynamicバイトコードを導入するまで、JVMに動的に型指定されたOO言語を実装することは非常に困難でした。パフォーマンスに悪影響を及ぼし、スタックトレースがひどく肥大化する複雑な回避策を使用する必要がありました。

それでも、それ以前のJVMには多数の動的言語(Groovy、Jython、JRubyなど)が実装されていました。

JVMが非常に用途が広いからではなく、非常に広く普及しているため、そして非常に成熟し、十分にサポートされ、高性能な実装を備えているためです。

そして、おそらくもっと重要なことは、そこには非常に多くのJavaコードがあり、ほとんど何でもしていることです。また、言語がJVMで実行される場合、そのコードと統合する機能を簡単に提供できます。基本的に、JVMで言語を実行することは、Cとの相互運用性を提供する21世紀のバージョンです。


良い答え(+1)。最後に述べたポイントは、言語としてのJavaの人気にも責任があるIMHOです。最終的に、無料で再利用できる膨大な量のコードがあることで、最新で最もファッショナブルな言語を使用するよりもはるかに多くの時間を節約できます特徴。
ジョルジオ

4

JVMは基本的にCPUのように動作するように記述されており、VMが実行するバイトコードと呼ばれる一連の命令(アセンブリのようなもの)があります。有効なバイトコードのセットを生成するコンパイラを作成できる場合、JVMはそれらを実行できます。

ウィキペディアには、バイトコードのリストがあります。

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

JVMがどのようにバイトコードをロードするかの説明と同様に:

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

呼び出しスタイルのバイトコードを使用することにより、ソースがどのように見えるかに関係なく、関数型言語はコードを実行できます。また、invokevirtualの追加により、jrubyのような言語実装は、実行方法にある程度の柔軟性を与えています。


1
YARV Ruby VM、Rubinius Ruby VM、CPython VM(これはすべてJVMよりも前のものです)、Parrot、さまざまなSmalltalkおよびLisp VM、そしてもちろんPascal P-コードシステム。その後、JVMがモデル化されます。
ヨルグWミットタグ

同意して、JVMは間違いなく最初のVMではありません。Javaが普及し、VMが積極的に開発され、十分に文書化されているため、JVMは他の言語で普及していると思います。
サズベリー

2

JVMは、明確に定義されたかなり適切なメモリモデル(JMM)をサポートすることを追加します。これは、一貫した(低レベルではあるが)スレッド化動作の良好なサポートを意味します。また、強力なJust In Timeコンパイラーもあります(MethodHandlesとinvokedynamicのおかげで、動的言語にはあまり役立ちません)。

最後になりましたが、JVMのGarbage Collectionサブシステムは(適切なチューニングを行って)上位の言語に関係なくメモリを管理します。


JMMは、Javaに関して私が最も好きではないものの1つです。私は効果的に不変のデータ(たとえば、コンテンツが他のスレッドに表示された後に決して変更されない配列)のファンですsomeField = new int[]{42};が、新しい配列を見るスレッドが値を見るようにする唯一の方法のようなステートメントを与えられました42は、いずれかのフィールドを作るためにありますfinalvolatile。フィールドを遅延生成したが、それは作り、頻繁にアクセスされている場合はfinal動作しません、そして作りそれはvolatile、それがアクセスされるたびに不要な同期ペナルティを課すことができます。最も緩い.NETモデルでも
...-supercat

...コードは、参照の格納の前に配列の移植が発生することを要求できます。フィールドを読み取る他のスレッドは、新しい配列への参照を参照する場合としない場合がありますが、新しい配列を参照した場合、その内容が表示されることは保証されません。
-supercat

1

これの重要な要素は、コンパイルを実行フェーズから分離することです。これにより、他の言語をコンパイルする他のコンパイラをバイトコードに書き込むことができます。

バイトコードはCPUのマシンコードと同様に機能します-プログラムを実行するために必要な小さな操作がすべてあります-変​​数の取得、計算、条件付き操作などができます。

Javaも特別ではありません。Javaでは、他のVMとは異なり、複数の言語の存在は設計目標でもありませんでした。以下のためにマイクロソフトの.NET CIL(C#、VB.Net、...)複数の言語を実行する能力も、重要な設計要素だったParrotVMは、一般的なVMであることを目的としたPerl6のプロジェクトから。

面白くするために、PHPのZend Engineでもそれが可能になるという証拠を作成しまし

そして率直に言って、これは新しいものではありません-実際のハードウェア上でも、複数の言語(CやFortranなど)を実行できます。

コンパイルと実行からのこの分離の違いは、Basic、シェルスクリプトなどの一部の形式のような古典的なインタープリターです。多くの場合、コードをすぐに実行せずに行ごとに実行するように動作します。間に。


1

JVMは、ガベージコレクション、パフォーマンス、および実行可能なサンドボックスモデルを組み合わせた最初の仮想マシンです。JVMをサポートするための多くの言語の出現は、おそらくその「汎用性」の結果ではなく、Java言語にはプログラミング言語に必要な重要な機能が欠けているためです。たとえば、ほとんどの機械語はデータ型が半ダースほどしかありませんが(バイト、ハーフワード、ワード、ダブルワード、単精度浮動小数点数、倍精度浮動小数点数など)、ほとんどのプログラミング言語ではコードを使用できます任意の数のユーザー定義データ型。JVMは、典型的なマシンのものと同様のいくつかのプリミティブ型に加えて、もう1つの型、無差別オブジェクト参照を認識します。Java言語も同様にこれらのプリミティブを認識しますが、無差別オブジェクト参照。変数は、特定のクラスではないものへの参照を保持しないように制限されている場合がありますが、言語では、次の種類のフィールドの種類を区別しません。List<String>インスタンスMyThingクラスによって保持される可能性がありますMyClass

  • コードへの参照は、不変の実装であることがわかっています List<String>

  • 変化する可能性のあるものに決してさらされない、変更可能なリスト型のインスタンスへの参照。

  • MyThingsのメソッドの実行中を除き、ユニバースのどこにも他の参照が存在しない可能性がある可変リストへの参照。

  • 他のオブジェクトが所有する可変リストへの参照。他のオブジェクトはMyThing何らかの方法で使用したいものです。

  • MyThing所有しているが、他のオブジェクトに公開されているため、彼らが何かを行うことができる可変リストへの参照。

これらのフィールドはすべてtypeを持つことができますがList<String>、非常に異なるものを保持しています。表現力豊かな言語では、これらの意味を区別できますが、Javaではできません。言語はそのようなものに意味を付け(少なくとも一般的なコンテキストの外で)、JVMで実行できるため、JVMターゲット言語がJavaができない概念を表現する余地を残しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.