メインコンテンツまでスキップ

構文ガイド

JAL のソースファイルには,一つのクラスまたはインターフェースを定義します。クラスの中にフィールドとメソッドを書き,メソッドの中に命令を並べます。

public class HelloWorld (major_version=55, minor_version=0) {
public static main([Ljava/lang/String;)V {
getstatic java/lang/System->out:Ljava/io/PrintStream;
ldc "Hello, World!"
invokevirtual java/io/PrintStream->println(Ljava/lang/String;)V
return
}
}

このまま Jaspera に貼り付けて実行できます。

空白とコメント

改行とインデントは命令の意味を変えません。このドキュメントでは一行に一命令を書き,メソッド本体を一段下げます。ラベルはメソッド宣言と同じ深さに置きます。

// から行末まではコメントです。複数行のコメントには /* ... */ を使います。文字列は二重引用符で囲みます。

クラス宣言

public final class examples/Empty (major_version=55, minor_version=0) {
}

クラス名は JVM 内部名です。パッケージ区切りには / を使います。括弧内には 名前=値 の形でメタデータを書き,複数指定する場合はコンマで区切ります。

名前指定するもの
major_versionクラスファイルのメジャーバージョン
minor_versionクラスファイルのマイナーバージョン
super_class親クラスの内部名。通常,省略時は java/lang/Object
interfaces実装するインターフェースの内部名

バージョン番号の意味は クラスファイルの見方 を参照してください。

フィールド宣言

private count:I
public static final MESSAGE:Ljava/lang/String; = "ready"

フィールド名の後ろに : と型記述子を書きます。Ljava/lang/String; の末尾のセミコロンは記述子の一部です。I にはセミコロンを付ける必要はありません。

= 値 はクラスファイルの定数値属性を指定します。Java の任意の初期化式とは異なります。インスタンスフィールドへの代入はコンストラクタなどで putfield を使います。詳しくは クラス,フィールド,メソッド で説明します。

メソッド宣言

public static add(II)I {
iload_0
iload_1
iadd
ireturn
}

メソッド名の直後に,引数型を囲む () と戻り型を書きます。上の例は二つの int を受け取り,その和を返します。static なので引数はスロット 0 と 1 に入ります。

インスタンスメソッドではスロット 0 が this です。同じ引数なら iload_1iload_2 で読み出します。iload_0 で参照型の this を読み出すことはできません。

抽象メソッドには空の {} を付けます。宣言の例は インターフェースと抽象メソッド を参照してください。コンストラクタ名は <init>,クラス初期化メソッド名は <clinit> です。

メンバー参照

java/lang/System->out:Ljava/io/PrintStream;
java/io/PrintStream->println(Ljava/lang/String;)V

-> の左側は参照するクラスまたはインターフェースの内部名です。右側はメンバー名と記述子です。フィールドでは : を挟み,メソッドでは引数の括弧を続けます。

ラベル

public static positive(I)Z {
iload_0
ifle NonPositive
iconst_1
ireturn
NonPositive:
iconst_0
ireturn
}

NonPositive: は命令の位置に名前を付けるラベルです。ラベル自身はバイトコードを生成しません。ifle はスタックから整数を取り出し,0 以下なら指定した位置へ分岐します。