- ASMは、JVMのバイトコードを読み書きするためのJavaライブラリです。
- これはコンパイル済みの.classファイルを対象とするため、再コンパイルすることなくクラスを書き換えることができます。
- MODは、ロード時にすでにコンパイルされたゲームをパッチ修正するためにこれを使用します。
- 多くのMOD製作者は、ASMの上に構築され、詳細を隠蔽するMixinを使用しています.
ASMは、JVMのバイトコードの読み込み、変更、書き込みを行うためのJavaライブラリです。ソースコードではなくコンパイル済みの.classファイルを対象とするため、再コンパイルすることなくクラスを検査または書き換えることができます。MinecraftのMODは、ゲームのロード時にパッチを適用できるため、ASMを活用しています.
ASMが実際に何をするのか
ASMはコンパイルされたクラスを、プログラムが編集できるものに変換します。.classファイルは単なるバイトコードであり、Java仮想マシンが実行する命令です。ASMは、そのバイトコードを解析し、メソッドとフィールドをあなたに渡し、命令の追加、削除、変更を許可します。そして、新しい有効なクラスを書き出します。
通常のJavaでは、これは単独ではできません。コンパイラは、あなたのソースを一度バイトコードに変換し、その後、そのバイトコードは固定されます。ASMは、通常記述するソース層より下の、バイトコードレベルで介入します
仕組みはこうです
ASM は ClassReader でクラスを読み込み、ClassWriter で書き込みます。その間、あなたのコードはクラスのパーツを訪問し、変更する内容を決定します。これには 2 つの方法があります。
Visitor アプローチは、クラスを要素ごとに 1 つずつ処理します。これは高速で、クラス全体を一度に保持しないため、メモリ使用量が少ないです。一方、Tree アプローチは、クラスを自由に歩き回って編集できるオブジェクトにロードするため、大規模な変更には理解しやすく、しかしより多くのメモリを使用します。
| アプローチ | 仕組み | 最適な用途 |
|---|---|---|
| Visitor API | クラスのイベントを読み取りながらストリーム処理します | メモリ使用量を抑えた、小規模で高速な編集 |
| Tree API | クラスの編集可能なオブジェクトモデルを構築します | 大規模または複雑な書き換え |
なぜ Minecraft モッドが使う
モッド開発者は、自身が書いたものではなく、再コンパイルもできないゲームコードを変更する必要があります。ゲームはコンパイルされたクラスとして出荷されるため、侵入できるのはバイトコードレベルのみであり、それがASMが提供するものに他なりません。モッドは、ゲームメソッドにフックを注入したり、呼び出しをリダイレクトしたり、フィールドを追加したりといった操作を、起動時に行うことができます。
ほとんどのモッダーが手動でASMを呼び出すことはありません。彼らはMixinを使用します。これはASMの上に構築された高レベルのフレームワークであり、シンプルなアノテーションをASMによるバイトコード編集に変換します。変更内容を記述した小さなJavaクラスを書くだけで、フレームワークがASMを使って低レベルな作業を代行してくれます。Fabricのモッドは特に、このチェーンに依存しています。
ASMを直接操作するケース
モッド開発者が生のASMを直接記述することは稀です。これは、ローダー、オブスクレータ、あるいはクラス全体を書き換えるパッチャーなど、アノテーションでは表現できないより高度な制御が必要なツールに現れるものです。日常的なモッドであれば、アノテーション層があれば十分であり、はるかにエラーが発生しにくいです。
よくある質問
いいえ、違います。逆コンパイラは、バイトコードを読みやすいソースコードに戻します。ASMはバイトコードそのものに対して動作し、ソースコードを復元するのではなく、変更するように設計されています。
通常は必要ありません。ほとんどのFabric MODはMixinを使用しており、ASMの詳細をアノテーションで隠しています。細かな制御が必要な場合にのみ、ASMを直接使用します。
いいえ。ASMは、バイトコードを扱う多くのツールで利用される一般的なJavaライブラリです。MinecraftのMOD開発はその一般的な用途の一つに過ぎません。
ソースコードを編集することはできません。ゲームは変更や再ビルドができないコンパイルされた状態で出荷されます。所有していないコードを修正する現実的な方法は、バイトコードを編集することです。