記事
【手書きで学ぶ JVM 入門】 第1回:Jaspera で最初の一歩
最新の JVM アセンブラ用 Web IDE「Jaspera」を使って,バイト・コードを手書きしてみましょう。JVM に直接命令を与えることで,Java の世界をより深く理解できます。今回は Jaspera の基本的な使い方から。
こんにちは。yamad です。
私はつい先日「セキュリティ・キャンプ ミニ 2026 (愛知開催)」の「バイト・コードを手書きして君も Java 仮想マシンになろう!」という講義に参加してきました(この話はまた今度詳しく書こうと思います)。 今回は,そこで生まれた思わぬ副産物についてお話いたします。
皆さんは,Java のプログラムがどのように動いているのか,気になったことはありませんか? 普段書いている Java のソース・コードは,コンパイルすると「バイト・コード」という命令列になり,Java 仮想マシン(JVM)で実行されます。 ということは,その命令を自分で書けば,JVM に直接指示を出せるわけです。
今回から始める「手書きで学ぶ JVM 入門」では,実際にバイト・コードを書いて動かしながら,JVM の仕組みを覗いていこうと思います。 まずは,そのための道具「Jaspera」を紹介しましょう。
IMPORTANT
なお,筆者は怠惰でありますから,次回がいつになるかは分かりません。 気になることがあったら,更新を待たずに,どんどん自分で調べたり試したりしてみてください。 筆者を置いて先に進んでしまっても,もちろん構いませんよ!
Jaspera について#

Jaspera とは,JVM バイト・コードを手書き・実行するための最新 Web IDEです。 バイト・コードを手書きするための様々なコード支援機能が備わっており,バイト・コードを学ぶのに最適な環境なのであります。
ここでいう,コード支援機能には,以下のようなものがあります:
-
構文ハイライト: バイト・コードの命令やラベル,コメントなどを色分けして表示します。
-
コード補完: バイト・コードの命令やラベルを補完してくれます。
-
高度なデバッガ: ブレークポイントを設定して,ステップ実行や変数の値の確認ができます。
ステップ・イン,ステップ・オーバー,ステップ・アウトなどの操作も可能です。 -
逆アセンブラ: クラス・ファイルを逆アセンブルして,有効なバイト・コードを表示します。
NOTE
デバッガと連携し,例えば標準ライブラリ・クラスへのステップ・イン時には逆アセンブル結果で表示され, ステップ実行が可能です。
TIP
クラス・ファイルが格納された jar ファイルや zip ファイルを D&D すると,すべて逆アセンブルして表示されます。一部ファイル,一部命令列の編集後,まとめて jar/zip ファイルで保存する機能もあります。
-
命令辞書: バイト・コードの命令の一覧を表示し,命令の意味やオペランドの種類を確認できます。
スタックやローカル変数の動きも視覚的に分かりやすく表示されます。 -
フレーム可視化: コード上の命令列をマウスでホバーすると,その命令によって発生するフレーム状態の遷移を確認できます。
スタックやローカル変数の状態を視覚的に確認できるので,バイト・コードの理解が深まります。 -
多言語対応: 上記のすべての機能と IDE の UI は,日,英,中,仏,西,伊,羅(ラテン語)に対応しています。
-
豊富なテーマ: IDE のテーマは,ダーク系,ライト系,カラフル系など,豊富なテーマを用意しています。
-
オフライン実行: あらかじめ端末に IDE と実行環境(約 60MB)を保存しておくことで,インタネットにアクセスできない環境であっても IDE を使用できます。
太古の時代から,バイト・コードを手書きするためには Jasmin のような専用アセンブラをローカル環境に構築して,いちいちコンパイルして実行する必要がありました。 しかし,Jaspera ではブラウザだけで記述から実行,デバッグまで完結できます。
Jaspera が生まれた経緯#
私の講義では,受講生の皆さんに JAL 言語を書いてもらう予定でした。 JAL は JVM バイト・コード用の新しいアセンブリ言語で,最新の JVM で動作し,文法も Java 話者と親和性が高いという特徴があります。
JAL は Javasm プラグインを用いて IntelliJ IDEA と連携することで,IDE による支援を受けながら書けるものであります。 受講生の皆さんにも,当然これを使ってもらおう,と講義の3日ほど前まで考えておりました。
事前学習として IDEA の環境構築をしてもらったのですが,その過程で,どうやら最新の IntelliJ IDEA は(あまりにもリッチすぎて)当日持ち込んでもらうラップトップで使うのは難しい,ということが分かりました。 プロジェクトを開くのに数十秒かかってしまいますし,1文字打つごとに小さなフリーズが発生してしまうのです。
これはいけない,と思い色々考えた結果,Web IDE にまるごと作り変えてしまう選択肢に気が付きました。
急遽 GPT-6 Astra に Javasm のソース・コードを丸々投げて頼んでみたところ,それっぽいものが 40 分で出来たことですから,そこからさらに改良を重ねて,最終的に今の Jaspera が完成しました(ここまで一晩です)。
実際に講義で用いてみたところ,受講生・チュータの方々から好評をいただき,作った甲斐があったなぁ,というところであります(実際にコードを書いたのは AI ですけどね😂)。
Jaspera を使ってみよう!#
さて,ここからが本題です。
Jaspera を使うためには,まず https://jaspera.yamad.jp にアクセスしてください。 読み込みが終わると,テーマ設定画面が表示されますから,お好きなテーマを選びましょう。
(言語は端末の設定から自動で選ばれます。もし意図したものと異なる場合は Alt + V を押し,一番下の項目から設定できます。)
まずはハロー・ワールド!#

Jaspera を開くと,左の「ファイル・ツリー」にサンプル・ソースがいくつか表示されます。
HelloWorld.jal が選択され,「エディタ」にそのソース・コードが表示されていると思います。
まずは実行してみましょう。右上の「実行」ボタンを押下するか,Ctrl + Enterキーを押下すると現在開かれているコードが実行されます:

命令を理解する: 命令辞書#
特に JVM バイト・コードにまだ慣れていない方は,或る命令が何をするのか全く分からないでしょう。 そこで Jaspera には「命令辞書」が搭載されており,選択した命令の解説がことこまかに表示されます。 右タブ「命令辞書」から開いてみましょう。
![]()
命令辞書には,命令の簡単な説明と使用例に加えて,「実行するとフレームがどうなるか」が図で表示されます。 (フレームの説明は後述します)

TIP
こんな感じで,エディタ内の命令をクリックしても,命令辞書が開きます!

命令を理解する: フレーム可視化#
エディタ内の命令をホバーすることで,その命令がフレームにどう影響するのかを把握できます。
NOTE
フレーム とは,メソッドを実行するための専用の作業領域のことです。主にオペランド・スタックとローカル変数配列 で構成されています。オペランド・スタックとは,命令が扱うデータの入出力に使用されるスタックです。
ほとんどの命令は,オペランド・スタックに値を出し入れするもので,一方でごく一部の命令はローカル変数配列のデータを扱います。オペランド・スタックを用いて計算を行い,一連の計算結果をローカル変数配列に入れて保存する,という考え方で説明できます。

invokevirtual 命令をホバーしてみると,PrintStream オブジェクトと引数たる文字列がスタックから取り出されていることが一目でわかります(厳密には,それぞれのオブジェクトへの参照が積まれており,それが取り出されます)。
命令を理解する: デバッガを使う#
デバッガを使うと,ブレーク・ポイントを用いて処理を止めたり,ステップ実行を用いて命令を1つ1つ実行できて便利です。

「HelloWorld」を開き,右上の「実行」ボタン右側の矢印を押下し,開いたメニューにある「デバッグ」を押下します。

そうするとデバッグが始まり,invokevirtual 命令にあるブレーク・ポイントで実行が一時停止されます。
NOTE
ブレーク・ポイントとは,プログラムの実行を指定行数・処理で一時停止する機能です。
一時停止中に変数を覗いたり,思考をしたりしてバグの原因を突き止めるのに使用します。
Jaspera では,行番号と命令オフセットの間をクリックすると,設置・削除ができます。

デバッグ中には,画面下部のデバッグ・メニューが使用できます;

左から次の操作に対応します:
- 再開: ブレーク・ポイント等で一時停止した処理を再開します。
- ステップ・オーバ: 次の命令まで実行を進めます。メソッドを呼び出す場合は,呼び出し先の処理をまとめて実行し,戻ってきたところで一時停止します。
- ステップ・イン: メソッドを呼び出す命令で一時停止しているとき,そのメソッドの中に潜って一時停止します。
- ステップ・アウト:現在のメソッドから戻るまで実行を進め,呼び出し元で一時停止します。
- 停止: プログラムの実行を停止します。
- ブレーク・ポイントを無視: 設置されたすべてのブレーク・ポイントを無視して実行します(トグル)。
ステップ・オーバ#
命令を1つ1つ実行して,状態遷移を見てみましょう。 ブレーク・ポイントで一時停止した状態で,メニュー左から2番目のボタンを押下すると⋯⋯

このように,ブレーク・ポイントで一時停止していた命令が実行され,その次の命令で,また一時停止します。 右側の「デバッグ」画面に表示されているフレームの状態も変わっていることが分かります。
ステップ・オーバ 機能を使用すると,命令を1つ1つ確認しながら実行できるのです。
ステップ・イン/ステップ・アウト#
ステップ・インは,次の命令まで実行を進める操作です。 メソッドを呼び出す命令で使用すると,呼び出し先のメソッドに入って一時停止します:

NOTE
ステップ・インを使用すると,呼び出されたメソッドの JAL コードが表示されます。 それが標準ライブラリや外部のクラス・ファイルであれば,自動で JAL コードへ逆アセンブルされます。
潜ったメソッドから復帰したい場合は,ステップ・アウトを使いましょう。

このように,現在のメソッドから戻るまで実行が進み,呼び出し元で再び一時停止します。
プログラムを書いてみよう!#
さて,使い方が分かったところで,自分でも命令を書いてみましょう。 今回は,2 + 3 を計算して,その結果を表示してみます。
HelloWorld.jal を開き,main メソッドの中身を次のように書き換えてください。
クラスやメソッドの宣言は,そのままで大丈夫です。
getstatic java/lang/System->out:Ljava/io/PrintStream;
// ...
// ...
iadd
invokevirtual java/io/PrintStream->println(I)V
return
さて,このままでは iadd 命令が取る値がスタックに積まれていません。
コメントの部分に何らかの命令を入れてあげると良さそうです。
他の example や 命令辞書とにらめっこしながら,ぜひぜひ実装してみてくださいね! (答え合わせはまた今度)
さいごに#
今回は,JVM バイト・コードをブラウザで手書き・実行できる「Jaspera」を紹介しました。 講義のために急遽作ったものではありますが,せっかくなので,受講生以外の皆さんにも使っていただければ嬉しいです。
普段 Java を書いていると,スタックに値を積んだり,そこから取り出したりする処理を意識する機会はあまりないかもしれません。 自分で命令を書いて,1つずつ実行してみると,いつものプログラムが少し違って見えてくると思います。
皆さんも,ぜひバイト・コードを手書きして Java 仮想マシンの気持ちを味わってみてください。
では,良き Java 仮想マシン・ライフを!