[解決済み] Javaの仮想マシンとCLR
質問
という質問のフォローアップのようなものです。
MSILとJavaバイトコードの違い?
という質問のフォローとして、Java仮想マシンの動作とMSILの動作の(主要な)違いや類似点は何ですか?
.NET フレームワーク
共通言語ランタイム (CLR) がどのように動作するか?
また
.NET フレームワーク
CLR は "仮想マシン" なのでしょうか、それとも仮想マシンの属性を持たないのでしょうか?
どのように解決するのですか?
両方の実装には多くの類似点があります (そして私の意見では、そうです、どちらも "仮想マシン" です)。
たとえば、これらは両方ともスタック ベースの仮想マシンであり、x86 や PowerPC のような最新の CPU で見慣れた「レジスタ」の概念はありません。すべての式((1 + 1) / 2)の評価は、オペランドをスタックにプッシュし、命令(加算、除算など)がオペランドを消費する必要があるときにオペランドをスタックからポップすることによって実行されます。各命令は、その結果をスタックにプッシュし直します。
世界中のほとんどすべての CPU がスタックを持っていますが、レジスタの数はしばしば異なるため、これは仮想マシンを実装するのに便利な方法です (一部のレジスタは特殊で、各命令は異なるレジスタにオペランドを期待する、など)。
ですから、抽象的なマシンをモデル化するのであれば、純粋にスタックベースのモデルはかなり良い方法だと言えます。
もちろん、実際のマシンはそのように動作しません。そのため、JIT コンパイラーはバイトコード操作の "enregistration" を実行する責任があり、基本的に可能な限りオペランドと結果を含むように実際の CPU レジスタをスケジューリングします。
つまり、それがCLRとJVMの間の最大の共通点の1つだと思うのです。
違いとしては...
2 つの実装の興味深い違いの 1 つは、CLR には汎用型を作成するための命令が含まれており、次にそれらの型にパラメトリックな特殊化を適用するための命令が含まれていることです。そのため、実行時に、CLR は List<int> を List<String> と完全に異なる型と見なします。
しかし、それぞれの値型は独自の実装を使用します (List<int> は List<double> と完全に異なるコードを生成します)。
Java では、ジェネリック型は純粋にコンパイラーのトリックです。JVMはどのクラスが型引数を持つかという概念を持たず、実行時にパラメトリックな特殊化を実行することができないのです。
実用的な観点からは、それは、ジェネリックタイプでJavaメソッドをオーバーロードできないことを意味します。同じ名前で、List<String> または List<Date> を受け入れるかどうかだけが異なる、2 つの異なるメソッドを持つことはできません。もちろん、CLRはパラメトリック型について知っているので、ジェネリック型の特殊化でオーバーロードされたメソッドを処理することに問題はありません。
日常的に、これが私が CLR と JVM の間で最も気がつく違いです。 JVM との間の最も顕著な違いです。
その他の重要な違いは以下の通りです。
-
CLRにはクロージャがある(C#のデリゲートとして実装されている)。JVMはJava 8以降のみクロージャをサポートしています。
-
CLRはコルーチン(C#の「yield」キーワードで実装)を持っています。JVMはそうではありません。
-
CLR はユーザー コードが新しい値型 (構造体) を定義することを可能にしますが、JVM は値型 (byte, short, int, long, float, double, char, boolean) の固定コレクションを提供し、ユーザーが新しい参照型 (クラス) を定義することのみを可能にします。
-
CLR はポインターの宣言と操作のサポートを提供します。これは、JVM と CLR の両方がメモリ管理戦略として厳密な世代別コンパクト化ガベージコレクタ実装を採用するため、特に興味深いものです。なぜなら、あるメモリ位置から別のメモリ位置に値を移動すると、すべてのポインタ(およびポインタへのポインタ)が無効になってしまうからです。しかし、CLRにはピン留めというメカニズムがあり、開発者はCLRが特定のポインタを移動してはいけないコードのブロックを宣言することができます。これはとても便利です。
-
JVM におけるコードの最大の単位は、'protected' キーワードによって証明されるように 'package' であるか、またはクラスパスで jar を指定でき、それがコードのフォルダーのように扱われることによって証明されるように、おそらく JAR (i.e. Java ARchive) であるかのいずれかです。CLR では、クラスは「アセンブリ」に集約され、CLR はアセンブリ (これは "AppDomains" にロードされ、メモリ割り当てとコード実行にサブアプリケーション レベルのサンドボックスを提供します) について推論し操作するためのロジックを提供します。
-
CLR バイトコード形式 (MSIL 命令とメタデータで構成される) は、JVM よりも少ない命令タイプを持っています。JVMでは、すべてのユニークな操作(2つのint値の加算、2つのfloat値の加算など)は、それ自身のユニークな命令を持っています。CLRでは、MSIL命令はすべてポリモーフィック(2つの値を足す)であり、JITコンパイラーはオペランドの型を決定し、適切な機械語を作成する責任を負う。どちらが望ましい戦略なのか、私にはわかりません。どちらにもトレードオフがあります。JVM 用の HotSpot JIT コンパイラーは、より単純なコード生成メカニズムを使用できますが (オペランドのタイプを決定する必要はありません。なぜなら、オペランドはすでに命令にエンコードされているからです)、それはより多くの命令タイプで、より複雑なバイトコード形式が必要であることを意味します。
私は約 10 年間 Java を使用してきました (そして JVM に感心していました)。
しかし、私の意見では、CLRはほとんどすべての点で優れた実装であると思います。
関連
-
Enumとの組み合わせでswitchの使い方を一度覚えるために必要な定数式
-
[解決済み] C#のStringとstringの違いは何ですか?
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Javaにおけるpublic、protected、package-private、privateの違いは何ですか?
-
[解決済み] serialVersionUIDとは何ですか、またなぜそれを使用する必要がありますか?
-
[解決済み] リフレクションとは何か、なぜ有用なのか?
-
[解決済み] Javaで配列を宣言し、初期化する方法は?
-
[解決済み] .NETでのdecimal, float, doubleの違い?
-
[解決済み] Microsoft Officeをインストールせずに、C#でExcel(.XLSおよび.XLSX)ファイルを作成するにはどうすればよいですか?
-
[解決済み】なぜJavaの+=, -=, *=, /=複合代入演算子はキャスティングを必要としないのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
SpringBootApplication を型解決できない。
-
Javaクラスローダーにソースコードから潜り込む
-
スキャナは、タイプに解決することはできません最もルーキー初心者の質問
-
VMの初期化中にエラーが発生しました java/lang/NoClassDefFoundError: java/lang/Object
-
リソースの読み込みに失敗しました。サーバーはステータス500(内部サーバーエラー)で応答しました。
-
Error: java.lang.NoClassDefFoundError: クラス XXXX を初期化できませんでした
-
SocketTimeoutExceptionの解決方法です。読み込みがタイムアウトした
-
Exception: java.util.NoSuchElementException: 行が見つかりません
-
java -serverコマンドで「Error: no `server' JVM at ... jvm.dll」を解決する方法です。
-
ブラウザでの大容量ファイルスライスアップロード(Javaサーバサイド実装)