逆コンパイルとは、ソースコードから実行可能コード・中間コード・別のプログラミング言語のソースコードなどを生成するコンパイルの逆の処理で、そのような生成されたコードから元となるソースコードを生成する処理である。
プログラミング言語は、基本的に機械が実際に実行するまでの間のどこかで、人間が読むための形式(通常はテキスト形式)を分析する構文解析の過程を経なければならない。構文解析後のデータをどのように扱うかは言語によって異なるが、そのまま実行したり(インタプリタ型言語)、再び構文解析を行うコストを省略するために中間コードや直接OSが実行できる実行可能コードの形で一旦保存しておいたり(コンパイル型言語)する。構文解析には付属して意味解析などのより高等な解析を行う場合もある。
現在(2017年11月)のJavaは、ソースコードをJavaバイトコードと呼ばれる中間コードにコンパイル(javacでのコンパイル)したのち、実行直前に実行可能コードにコンパイル(JITコンパイラでのコンパイル)して、それを実行させるという二度手間(機械語の解析を含めると三度手間)のコンパイル形態を持っている。このうち、JITコンパイラは当初は存在しなかった(バイトコードを解析しながら実行するインタプリタ型だった)らしいが、実行速度の面で新たに加えられた。MinecraftのMODの配布形式であるJARは、バイトコードであるclassファイルといくつかのその他のメタなファイルをZIP圧縮して拡張子を変えた奴である。どうせランタイムが必要ならソースコードの状態で配れよとか言わない。
Javaにおける逆コンパイルは専らJavaバイトコード(.class≒.jar)からJavaソースコード(.java)への変換であり、Javaにおける通常のコンパイル(javacおよびjar)の逆の変換を行うものである。この段階の処理は特定のOSに依存した実行ファイル(Windowsの場合は.exeファイルなど)は関与せず、そのためJavaのコンパイルおよび逆コンパイルではプログラマーはOSごとの違いを無視して作業を行うことができる。
この逆コンパイルという処理はJavaにおいては意外なほど簡単であり、Pleiades Eclipseに標準でくっついてきていたりする。そのため、Javaをコンパイルする際には基本的にソースコードが筒抜けになると考えておいた方が良い。
Minecraft界隈での逆コンパイルもJavaにおける逆コンパイルと同様で、バイトコードをソースコードに変換するものである。ただし、Minecraftでは難読化というプログラムを逆コンパイルから守る処理によって、単に逆コンパイルしただけではソースコードをまともに編集できない。
プログラミングではデータを格納する変数や動作を表す関数といったものに名前を付けて利便性を高めている。このような物の名前はJavaではバイトコードの段階でも維持され、プログラマー同士が互いのプログラムを理解するのに一役買っているが、難読化はこの名前を破壊しプログラマーのやる気を削ぐことで配布物を改造や解析などから守っている。
Minecraft Forgeでは、Moddingの際に難読化済みの名前に再び意味のある名前を付けることで難読化対策をしている。そして、ユーザーの実行環境のMinecraftは難読化されているため、意味のある名前のMODのバイトコードを難読化して配布している(Modding界隈では無印(難読化あり)とdev版(難読化なし)であり、IC2Expにも存在する)。
本サイトでは、ソースコードが見当たらないJavaプログラムについてソースコードと言ったら、実際に開発者の手元にあるソースコードではなく逆コンパイルして得られたJavaソースコード(略して逆コンパイルコード)を指すものとする。
特に逆コンパイル対策がされていないJarファイルは、EclipseやJD-GUIといった様々なツールからソースコードが見れる(JD-GUIならインストールしてD&D(ドラッグアンドドロップ)で済むので初心者でも割と簡単に見れる読解できるかは謎)が、ここではfernflowerを使う。これはどうやらMinecraft Forgeでも使われているようだ。
以下ではWindows 10/PowerShell/日本語環境でのインストールについて解説する。
fernflower.jarとIC2Expのdev版のjarを同一フォルダに置いてPowerShellから以下を実行。
結果、srcフォルダにソースコードが出力される。
このまま常にコマンドからfernflower.jarを呼び出してもいいが、できれば最低でもD&Dで実行したいのでバッチファイルを作る。
どこかしらに次のようなフォルダを作る
これで、fernflower.batに対してjarファイルをドロップするとjarファイルと同じフォルダに逆コンパイルされたコードが入ったフォルダが生成されるようになった。
このまま常にバッチファイルにドロップしてもいいが、できれば右クリックしたらこの場所にソースを生成するコマンドが欲しい。そこで、一連の動作を行うバッチファイルを作りレジストリを操作してJarファイルに関連付ける。
適当なJarファイルを右クリックしてdecompileという項目が増えていれば成功。
ここまでで様々なJarを逆コンパイルして.javaファイルの入ったフォルダが入手できるようになっているので、実際にdev版のIC2Expをダウンロードしてソースコードを得る。ここではソースコードを読みやすくするためのいくつかの点について触れる。
結局のところとりあえず読むならIDEを入れた方が早い。EclipseのJava版かUltimate版をダウンロードし、新規プロジェクトないしForgeプロジェクトを使って、srcフォルダに逆コンパイルコードをぶち込んでしまおう。
JarをJD-GUIに読み込ませてもコードハイライトや定義へのジャンプ機能など様々なことができるが、ソースのフォーマット(成形)やより高度な検索はIDEを使うのが良い。一応実行もできる。
別Verとの差分をとる場合、公式の更新履歴が信用できない場合は独自にコード差分をとることもできる。Mercurial(バージョン管理システム)のGUI(TurtoiseHG)上でコミットしてしまうのが分かりやすくて高機能か。
GregTech6 http://gregtech.overminddl1.com/com/gregoriust/gregtech/gregtech_1.7.10/index.html#Downloads
IC2Exp http://ic2api.player.to:8080/job/IC2_experimental/