- JVMのバイトコードは、Java仮想マシンが実行するコンパクトな命令セットです。
- Javaコンパイラは、ネイティブマシンコードではなく、
.classファイルにバイトコードを生成します。 - 同じ
.classファイルは、Javaランタイム環境を備えたどのプラットフォームでも実行でき、それがこの形式の目的です。 - モッドは、ソースコードなしにコンパイルされたゲームを変更するためにバイトコードを書き換えます.
Java仮想マシンが実行する命令セットが、JVMバイトコードです。Javaソースコードをコンパイルすると、コンパイラはCPU向けの機械語を生成しません。代わりに、コンパクトで移植性のあるバイトコードを.classファイルに格納します。JVMは実行時にこれらの命令を読み込み、必要に応じてネイティブコードに変換します.
どこ Opal 合う
ソースコードがバイトコードになる仕組み
.javaファイルは、人が書くテキストです。.classファイルは、JVMが実行するコンパイルされた出力です。コンパイラはあなたのソースコードを読み込み、チェックし、クラスごとに1つの.classファイルを書き込みます。各ファイルには、バイトコードの命令、定数プール、メソッドテーブル、その他のメタデータが含まれています。
バイトコードは特定のプロセッサに依存しません。同じ.classファイルは、Windows、macOS、Linux、またはJavaランタイムがあるものであればどこでも実行できます。なぜなら、JVMがローカルマシンで命令を実行する方法を知っているレイヤーだからです。この移植性は、この形式の目的そのものです。
命令の見た目
バイトコードはスタックベースの命令セットです。ほとんどの操作は、オペランドスタックに値をプッシュし、ポップし、結果をプッシュします。考慮すべきレジスタ割り当てはなく、モデルは意図的にシンプルなので、JVMはそれを迅速に検証および実行できます。
いくつかの例となるオプコードは、その雰囲気を伝えます。
| オプコード | 動作 |
|---|---|
iload | スタックにintローカル変数プッシュ |
iadd | スタックから2つのintをポップし、それらの合計をプッシュ |
invokevirtual | インスタンスメソッドを呼び出す |
getfield | インスタンスフィールドを読み取る |
return | メソッドから戻る |
これらのオプコードを直接読むことや書くことはほとんどありません。ツールが生成および消費します。そこで、ASMのようなライブラリが役立ちます。
モッドにとってバイトコードが重要な理由
バイトコードは、元のソースコードなしに動作を変更できるため重要です。MinecraftのMODは、ゲームのソースコードを持っていることはほとんどありません。代わりに、ディスク上のコンパイルされたゲームを持っています。機能を追加または変更するには、MODは既存のバイトコードを読み取り、書き換え、クラスがロードされる際にJVMに結果を戻します。
パッチングフレームワークが、所有していないメソッドにフックを挿入する方法です。コンパイルされたメソッド内の適切な場所を見つけ、MODのコードへの呼び出しをspliceします。バイトコードレベルで作業することで、MODは元のJavaの1行も見たことがないにもかかわらず、ゲームにアタッチできます。
ASMの役割
ASMは、バイトコードの読み取り、書き込み、変換を行うJavaライブラリです。.classファイルをイベントまたはツリーに解析し、コードが命令を変更できるようにし、有効な.classファイルを戻します。小さく、高速で、生のフォーマットに近いので、より高レベルのMOD作成ツールは、クラスファイルを直接解析するのではなく、ASMの上に構築します。
ほとんどのMOD作成者は、ASMを直接呼び出すことはありません。代わりに、オプコードを隠し、「このメソッドの開始時に私のコードを実行する」というよりフレンドリーな方法を公開する、より高レベルのレイヤーを使用します。そのレイヤーの下では、ASMを使用してバイトコードを編集しています。
FAQ
いいえ。機械語は特定のCPU向けのネイティブな命令です。バイトコードはJVM独自の命令セットであり、JVMが実行時に機械語に翻訳します。この追加の層が、.classファイルをどのプラットフォームでも実行できる理由です。
部分的に可能です。逆コンパイラはバイトコードから読みやすいJavaを再構築し、通常のコードであればかなり近い結果が得られます。結果は元のソースと完全に同じになるとは限りませんが、コメントや一部のローカル名が失われているものの、通常は追跡するのに十分です。
通常、MODにはソースコードがありません。コンパイル済みのゲームに対して配布されるからです。バイトコードを書き換えることで、MODは元のJavaファイルに触れることなく、あるいは持たなくても、ゲームの動作を変更できます。
通常は必要ありません。MOD作成フレームワークやスクリプトレイヤーがバイトコードの処理を代行します。問題のあるパッチのデバッグやツール作成の際に、その仕組みを知っていると役立ちます。