Java バイトコードにコンパイルします (Java を使用せず)
-
22-08-2019 - |
質問
私のコンパイラ クラスは、Java バイトコードにコンパイルする予定の言語を作成しています。かなりの進歩があり、コード生成の時期が近づいています。
コンパイラから .class ファイルを作成する方法に関する情報を見つけるのに問題があります。何か支援できるリソースはありますか?命令セットに関するドキュメントはすでにたくさんありますが、クラス ファイルに直接記入する方法や 16 進数の記述方法に関する情報が必要です。
.class ファイルの逆コンパイルに関する情報や提案は必要ありません。
.class ファイルを最初から書き出す簡単な例でも優れています。
JVM 仕様は私たちが求めているものではありません。 本当に必要なのは、例またはチュートリアルです。
解決
VM の仕様: クラスファイル形式 そしてその Java 仮想マシン命令セット やるべきだ。
バイト コード エンジニアリング ライブラリ (BCEL) インスピレーションのためだけでなく バグを見つける (クラスファイルを読んで理解する必要があります)。
他のヒント
自分でクラス ファイルを作成しなくても、Java クラス ファイルを作成するための高レベルのインターフェイスを提供するプロジェクトが多数存在します。以下をご覧ください。
- ASM - http://asm.objectweb.org/
- BCEL - http://jakarta.apache.org/bcel/
- トローブ - http://teatrove.sourceforge.net/trove.html
いずれもクラス ファイルを作成するための API を提供します。これを行うために彼らが書いたコードをいつでも見て、自分のコンパイラ用に同様のコードを書くことができますが、それはかなりの作業量であると思います。
BCEL を使用して ClassGen を見てください。これにより、必要な形式でクラス ファイルを書き出すことができるようになります。簡単な例を次に示します。
ClassGen cg = new ClassGen("HelloWorld", "java.lang.Object",
"<generated>", ACC_PUBLIC | ACC_SUPER,
null);
失望させて申し訳ありませんが、 VMのスペック は その通り あなたが何を求めているのか。仕様を扱えないのであれば、結局のところコンパイラを書くべきではないのかもしれません。
既存のツールを使用して、結果として得られるバイトコードに対する増分変更の影響を調べることができると思います。
ソース:
public class Hello {
public static void main(String[] args) {
System.out.println("H");
}
}
ジャバップ 出力:
Compiled from "Hello.java"
public class Hello extends java.lang.Object{
public Hello();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3; //String H
5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
バイナリ:
CA FE BA BE 00 00 00 32 00 1D 0A 00 06 00 0F 09 _______2________
00 10 00 11 08 00 12 0A 00 13 00 14 07 00 15 07 ________________
00 16 01 00 06 3C 69 6E 69 74 3E 01 00 03 28 29 _____<init>___()
56 01 00 04 43 6F 64 65 01 00 0F 4C 69 6E 65 4E V___Code___LineN
75 6D 62 65 72 54 61 62 6C 65 01 00 04 6D 61 69 umberTable___mai
6E 01 00 16 28 5B 4C 6A 61 76 61 2F 6C 61 6E 67 n___([Ljava/lang
2F 53 74 72 69 6E 67 3B 29 56 01 00 0A 53 6F 75 /String;)V___Sou
72 63 65 46 69 6C 65 01 00 0A 48 65 6C 6C 6F 2E rceFile___Hello.
6A 61 76 61 0C 00 07 00 08 07 00 17 0C 00 18 00 java____________
19 01 00 01 48 07 00 1A 0C 00 1B 00 1C 01 00 05 ____H___________
48 65 6C 6C 6F 01 00 10 6A 61 76 61 2F 6C 61 6E Hello___java/lan
67 2F 4F 62 6A 65 63 74 01 00 10 6A 61 76 61 2F g/Object___java/
6C 61 6E 67 2F 53 79 73 74 65 6D 01 00 03 6F 75 lang/System___ou
74 01 00 15 4C 6A 61 76 61 2F 69 6F 2F 50 72 69 t___Ljava/io/Pri
6E 74 53 74 72 65 61 6D 3B 01 00 13 6A 61 76 61 ntStream;___java
2F 69 6F 2F 50 72 69 6E 74 53 74 72 65 61 6D 01 /io/PrintStream_
00 07 70 72 69 6E 74 6C 6E 01 00 15 28 4C 6A 61 __println___(Lja
76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B 29 va/lang/String;)
56 00 21 00 05 00 06 00 00 00 00 00 02 00 01 00 V_!_____________
07 00 08 00 01 00 09 00 00 00 1D 00 01 00 01 00 ________________
00 00 05 2A B7 00 01 B1 00 00 00 01 00 0A 00 00 ___*____________
00 06 00 01 00 00 00 01 00 09 00 0B 00 0C 00 01 ________________
00 09 00 00 00 25 00 02 00 01 00 00 00 09 B2 00 _____%__________
02 12 03 B6 00 04 B1 00 00 00 01 00 0A 00 00 00 ________________
0A 00 02 00 00 00 03 00 08 00 04 00 01 00 0D 00 ________________
00 00 02 00 0E _____
の JVM仕様 おそらくあなたが探しているもの、特に 第 4 章 - クラスファイル形式.
SmartEiffel には、オープン ソースの Java .class ファイル ジェネレーターが含まれています。