1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Java の class ファイルを読み解く:定数プールとバイトコードを理解する

Last updated at Posted at 2025-08-23

筆者はアセンブリ言語が好きです。
javaにも中間言語のようなものが無いかと調べてみるとありました。
せっかくなので中身を覗いてみます。

バイトコード生成の手順

javaをコンパイルしてclassファイルを生成します。
その後javapを使うと簡単にバイトコードが見られます。

test.java
public class test {
    
    public static void main(String[] args){
        
        int a = 10;
        int b = 20;
        int c = a + b;
        System.out.println(c);
            
    }
}
test@test-ThinkPad-X280:~/test/javatest$ nano test.java 
test@test-ThinkPad-X280:~/test/javatest$ javac test.java
test@test-ThinkPad-X280:~/test/javatest$ java test 
30
test@test-ThinkPad-X280:~/test/javatest$ javap -v test
Classfile /home/test/test/javatest/test.class
  Last modified 2025年8月23日; size 400 bytes
  SHA-256 checksum b69fb5d281787a43a8e3cd9bcf0d2e5e96e6deea9ffa7a80086f8e972eb08a71
  Compiled from "test.java"
public class test
  minor version: 0
  major version: 61
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #19                         // test
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
   #2 = Class              #4             // java/lang/Object
   #3 = NameAndType        #5:#6          // "<init>":()V
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Fieldref           #8.#9          // java/lang/System.out:Ljava/io/PrintStream;
   #8 = Class              #10            // java/lang/System
   #9 = NameAndType        #11:#12        // out:Ljava/io/PrintStream;
  #10 = Utf8               java/lang/System
  #11 = Utf8               out
  #12 = Utf8               Ljava/io/PrintStream;
  #13 = Methodref          #14.#15        // java/io/PrintStream.println:(I)V
  #14 = Class              #16            // java/io/PrintStream
  #15 = NameAndType        #17:#18        // println:(I)V
  #16 = Utf8               java/io/PrintStream
  #17 = Utf8               println
  #18 = Utf8               (I)V
  #19 = Class              #20            // test
  #20 = Utf8               test
  #21 = Utf8               Code
  #22 = Utf8               LineNumberTable
  #23 = Utf8               main
  #24 = Utf8               ([Ljava/lang/String;)V
  #25 = Utf8               SourceFile
  #26 = Utf8               test.java
{
  public test();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: bipush        10
         2: istore_1
         3: bipush        20
         5: istore_2
         6: iload_1
         7: iload_2
         8: iadd
         9: istore_3
        10: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
        13: iload_3
        14: invokevirtual #13                 // Method java/io/PrintStream.println:(I)V
        17: return
      LineNumberTable:
        line 7: 0
        line 8: 3
        line 9: 6
        line 10: 10
        line 12: 17
}
SourceFile: "test.java"

定数プール

バイトコードから直接参照されている要素

   #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
   #7 = Fieldref           #8.#9          // java/lang/System.out:Ljava/io/PrintStream;
  #13 = Methodref          #14.#15        // java/io/PrintStream.println:(I)V

#7を組み立てる

#8 = クラス  → クラス名は "java/lang/System"
#9 = 名前+型  → フィールド名 "out", 型 "Ljava/io/PrintStream;"

   #8 = Class              #10            // java/lang/System
   #9 = NameAndType        #11:#12        // out:Ljava/io/PrintStream;
  #10 = Utf8               java/lang/System
  #11 = Utf8               out
  #12 = Utf8               Ljava/io/PrintStream;

#13を組み立てる

#14 = クラス → クラス名 "java/io/PrintStream"
#15 = 名前+型 → メソッド名 "println", メソッド記述子 "(I)V" 

  #14 = Class              #16            // java/io/PrintStream
  #15 = NameAndType        #17:#18        // println:(I)V
  #16 = Utf8               java/io/PrintStream
  #17 = Utf8               println
  #18 = Utf8               (I)V

(I)Vの意味

括弧の中 () = 引数の型
括弧の外(右側) = 戻り値の型
→ 「intを引数に取り、戻り値は voidのメソッド」

バイトコード解釈

コンストラクタ

javaのコードに書いていなくても自動的にコンストラクタが補完される模様。

 0: aload_0
 1: invokespecial #1                  // Method java/lang/Object."<init>":()V
 4: return

逆コンパイルしてもコンストラクタのjavaコードは出てこなかったが多分こんな感じ。
public test() { super(); }

変数a,bの代入

 0: bipush 10         // スタックに 10
 2: istore_1          // ローカル変数1 (a) に格納
 3: bipush 20         // スタックに 20
 5: istore_2          // ローカル変数2 (b) に格納

ここまでで a=10, b=20 が確定。

変数a,bの加算

 6: iload_1           // ローカル変数1 をスタックに積む (a)
 7: iload_2           // ローカル変数2 をスタックに積む (b)
 8: iadd              // スタック上の 2 値 (a+b) を加算し積む
 9: istore_3          // ローカル変数3 (c) に格納

ここで c = a + b が計算完了。

Sysyem.out.println()の呼び出し

10: getstatic  #7   // スタックに System.out (PrintStream型オブジェクト)
13: iload_3         // スタックに c (int)
14: invokevirtual #13 // PrintStream.println(int) 呼び出し
17: return

#7 は「System.out」という static フィールドの参照情報
#13 は「PrintStream.println(int)」というメソッドの参照情報

逆コンパイル

wget https://www.benf.org/other/cfr/cfr-0.152.jar -O cfr.jar
java -jar cfr.jar test.class --outputdir ./src
/*
 * Decompiled with CFR 0.152.
 */
public class test {
    public static void main(String[] stringArray) {
        int n = 10;
        int n2 = 20;
        int n3 = n + n2;
        System.out.println(n3);
    }
}
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?