2017-02-04 9 views
0

現在、私はjvmバイトコード命令を試しています。ソースコード(Cスタイルのようなもの)がjvmバイトコード表現を生成する単純なコンパイラを作った。たとえば、次のコード:jvmバイトコードからjavaクラスファイルヘッダを生成する

float x = 3; 
float y = 4.5; 
float z = x + y; 
print z; 

はコンパイルに:

ldc 3 
i2f 
fstore 1 
ldc 4.5 
fstore 2 
fload 1 
fload 2 
fadd 
fstore 3 
getstatic java/lang/System/out Ljava/io/PrintStream; 
fload 3 
invokevirtual java/io/PrintStream/println(F)V 
return 

(私は生成されたJavaコードは、現在のように、最も効率的ではありません知っているが、それはポイントではありません)。

Javaバイトコードエディタを使用して、コンパイルされたメインクラスをロードし、メインメソッドコードを自分のコードに置き換えました。その後、私はコードを完全にうまく使ってクラスファイルを実行することができました。私の質問は、Javaバイトコードを取り、クラスファイルの適切なヘッダーを生成できるUIを持たないツール/スクリプト(つまり、バイトコードを取り出して有効なクラスファイルを作成する)です。私は自分でスクリプトを書くことができると思うが、それは私が今持っていないかもしれない時間がかかるだろう。

+2

あなたはジャスミンを見ることができます。 –

+1

何らかのコンパイラを作成している場合は、それを有効にして "ヘッダ"自体を生成する必要があります。 [それは魔法ではありません](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html)。もちろん、[ASM](http://asm.ow2.org/)のようなライブラリを使用してタスクを簡略化することもできます。これは、ある種のテキストに情報を書式設定し、後で別のツールで解析できるようにするよりも優れています。実際には、最初はクラスファイルを生成する方が簡単です。 – Holger

答えて

2

Krakatau assemblerは、バイトコードをテキスト形式で書き出し、クラスファイルにアセンブルして、すべてのバイナリエンコーディングの詳細を処理します。

これは旧式のJasminアセンブラと似ていますが、あいまいさを取り除き、Jasminが処理できないクラスファイル機能をサポートするために、構文を少し変更しています。ジャスミンとは異なり、Java 8のクラスファイルフォーマット全体を完全にサポートし、オプションでクラスファイルのバイナリ表現を完全に制御することができます。

たとえば、ラムダをクラカタウのアセンブリ形式で使用するクラスがあります。

.version 52 0 
.class public super LambdaTest1 
.super java/lang/Object 

.method public <init> :()V 
    .code stack 1 locals 1 
     aload_0 
     invokespecial Method java/lang/Object <init>()V 
     return 
    .end code 
.end method 

.method public static varargs main : ([Ljava/lang/String;)V 
    .code stack 4 locals 2 
     invokedynamic InvokeDynamic invokeStatic Method java/lang/invoke/LambdaMetafactory metafactory (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; MethodType (J)J MethodHandle invokeStatic Method LambdaTest1 lambda$main$0 (J)J MethodType (J)J : applyAsLong()Ljava/util/function/LongUnaryOperator; 
     astore_1 
     getstatic Field java/lang/System out Ljava/io/PrintStream; 
     aload_1 
     ldc2_w 42L 
     invokeinterface InterfaceMethod java/util/function/LongUnaryOperator applyAsLong (J)J 3 
     invokevirtual Method java/io/PrintStream println (J)V 
     return 
    .end code 
.end method 

.method private static synthetic lambda$main$0 : (J)J 
    .code stack 4 locals 2 
     lload_0 
     lload_0 
     l2i 
     lshl 
     lreturn 
    .end code 
.end method 

.innerclasses 
    java/lang/invoke/MethodHandles$Lookup java/lang/invoke/MethodHandles Lookup public static final 
.end innerclasses 

.end class 
+0

私は本当に好きです。今は、行番号の代わりにラベルを使用するようにコードをフォーマットするだけです。 – Elldorin

関連する問題