Java's Virtual Machine and CLR Ask Question

Java's Virtual Machine and CLR Ask Question

As a sort of follow up to the question called Differences between MSIL and Java bytecode?, what is the (major) differences or similarity in how the Java Virtual Machine works versus how the .NET Framework Common Language Runtime (CLR) works?

Also, is the .NET framework CLR a "virtual machine" or does it not have the attributes of a virtual machine?

ベストアンサー1

There are a lot of similarities between both implementations (and in my opinion: yes, they're both "virtual machines").

For one thing, they're both stack-based VM's, with no notion of "registers" like we're used to seeing in a modern CPU like the x86 or PowerPC. The evaluation of all expressions ((1 + 1) / 2) is performed by pushing operands onto the "stack" and then popping those operands off the stack whenever an instruction (add, divide, etc) needs to consume those operands. Each instruction pushes its results back onto the stack.

It's a convenient way to implement a virtual machine, because pretty much every CPU in the world has a stack, but the number of registers is often different (and some registers are special-purpose, and each instruction expects its operands in different registers, etc).

So, if you're going to model an abstract machine, a purely stack-based model is a pretty good way to go.

Of course, real machines don't operate that way. So the JIT compiler is responsible for performing "enregistration" of bytecode operations, essentially scheduling the actual CPU registers to contain operands and results whenever possible.

So, I think that's one of the biggest commonalities between the CLR and the JVM.

As for differences...

One interesting difference between the two implementations is that the CLR includes instructions for creating generic types, and then for applying parametric specializations to those types. So, at runtime, the CLR considers a List<int> to be a completely different type from a List<String>.

Under the covers, it uses the same MSIL for all reference-type specializations (so a List<String> uses the same implementation as a List<Object>, with different type-casts at the API boundaries), but each value-type uses its own unique implementation (List<int> generates completely different code from List<double>).

In Java, generic types are a purely a compiler trick. The JVM has no notion of which classes have type-arguments, and it's unable to perform parametric specializations at runtime.

From a practical perspective, that means you can't overload Java methods on generic types. You can't have two different methods, with the same name, differing only on whether they accept a List<String> or a List<Date>. Of course, since the CLR knows about parametric types, it has no problem handling methods overloaded on generic type specializations.

日常的に、これが CLR と JVM の間で私が最も気づく違いです。

その他の重要な違いは次のとおりです。

  • CLR にはクロージャ (C# デリゲートとして実装) があります。JVM は Java 8 以降でのみクロージャをサポートしています。

  • CLR にはコルーチン (C# の 'yield' キーワードで実装) があります。JVM にはありません。

  • CLR ではユーザー コードで新しい値の型 (構造体) を定義できますが、JVM では値の型 (byte、short、int、long、float、double、char、boolean) の固定コレクションが提供され、ユーザーは新しい参照型 (クラス) のみを定義できます。

  • CLR は、ポインタの宣言と操作をサポートしています。これは、JVM と CLR の両方がメモリ管理戦略として厳密な世代別圧縮ガベージ コレクター実装を採用しているため、特に興味深いことです。通常の状況では、厳密な圧縮 GC はポインターの処理に非常に苦労します。値を 1 つのメモリ位置から別のメモリ位置に移動すると、すべてのポインター (およびポインターへのポインター) が無効になるためです。しかし、CLR は「固定」メカニズムを提供しているため、開発者は CLR が特定のポインターを移動できないコード ブロックを宣言できます。これは非常に便利です。

  • JVM のコードの最大単位は、「protected」キーワードで示される「パッケージ」か、クラスパスで jar を指定してコードのフォルダーのように扱えることからわかるように、JAR (Java ARchive) であると言えます。CLR では、クラスは「アセンブリ」に集約され、CLR はアセンブリの推論と操作のためのロジックを提供します (アセンブリは「AppDomains」にロードされ、メモリ割り当てとコード実行のためのサブアプリケーション レベルのサンドボックスを提供します)。

  • CLR バイトコード形式 (MSIL 命令とメタデータで構成) には、JVM よりも命令タイプが少なくなっています。JVM では、すべての一意の操作 (2 つの int 値を加算、2 つの float 値を加算など) に独自の命令があります。CLR では、すべての MSIL 命令はポリモーフィック (2 つの値を加算) であり、JIT コンパイラがオペランドの型を決定し、適切なマシン コードを作成する役割を担います。ただし、どちらが望ましい戦略かはわかりません。どちらもトレードオフがあります。JVM 用の HotSpot JIT コンパイラは、より単純なコード生成メカニズムを使用できます (オペランドの型は既に命令にエンコードされているため、決定する必要はありません)。ただし、これは、より多くの命令タイプを含む、より複雑なバイトコード形式が必要になることを意味します。

私は約 10 年間 Java を使い続け (そして JVM を賞賛してきました)。

しかし、私の意見では、CLR は現在、ほぼすべての点で優れた実装です。

おすすめ記事