Javaのクラスファイルを読む(javapモドキを作りたい).

先週,夏休みバイナリ入門 2012
というものに参加してきました.そのときは,jvmの日本語仕様書(英語版はこっち)を借りたり,配布されたされた資料(仕様書から該当場所を抽出し,解説を加えたもの)読んだりして,jvmのクラスファイルの構造がどうなっているかお勉強しました.コードを書く時間もあったのですが,時間内に終わりませんでした.

今,資料を読みながら,ちょろちょろ書いて,そこそこのものができたと思うので,一応ここに載せておきます.このプログラムは,javaのクラスファイルを定義通りに,Pythonの辞書に格納するだけのものです.
残念ながら,一部未実装のところがあるのでHello,Worldのクラスファイルぐらいしか読めないと思います.
あと,辞書なので,printすると順番が強制的にアルファベット順になってしまいます(仕方ないか).

javap.py

実行結果例

Code: B2 00 02 12 03 B6 00 04 B1 

{'access_flags': 32,
 'constant_pool': [{},
                   {'class_index': 6, 'name_and_type_index': 15, 'tag': 10},
                   {'class_index': 16, 'name_and_type_index': 17, 'tag': 9},
                   {'string_index': 18, 'tag': 8},
                   {'class_index': 19, 'name_and_type_index': 20, 'tag': 10},
                   {'name_index': 18, 'tag': 7},
                   {'name_index': 21, 'tag': 7},
                   {'bytes': '<init>', 'tag': 1},
                   {'bytes': '()V', 'tag': 1},
                   {'bytes': 'Code', 'tag': 1},
                   {'bytes': 'LineNumberTable', 'tag': 1},
                   {'bytes': 'main', 'tag': 1},
                   {'bytes': '([Ljava/lang/String;)V', 'tag': 1},
                   {'bytes': 'SourceFile', 'tag': 1},
                   {'bytes': 'Hello.java', 'tag': 1},
                   {'descriptor_index': 8, 'name_index': 7, 'tag': 12},
                   {'name_index': 22, 'tag': 7},
                   {'descriptor_index': 24, 'name_index': 23, 'tag': 12},
                   {'bytes': 'Hello', 'tag': 1},
                   {'name_index': 25, 'tag': 7},
                   {'descriptor_index': 27, 'name_index': 26, 'tag': 12},
                   {'bytes': 'java/lang/Object', 'tag': 1},
                   {'bytes': 'java/lang/System', 'tag': 1},
                   {'bytes': 'out', 'tag': 1},
                   {'bytes': 'Ljava/io/PrintStream;', 'tag': 1},
                   {'bytes': 'java/io/PrintStream', 'tag': 1},
                   {'bytes': 'println', 'tag': 1},
                   {'bytes': '(Ljava/lang/String;)V', 'tag': 1}],
 'fields': [],
 'interfaces': [],
 'magic': 3405691582,
 'major_version': 50,
 'methods': [{'access_flags': 0,
              'attributes': [{'attributes': [{'line_number_table': [{'line_number': 1,
                                                                     'start_pc': 0}],
                                              'name': 'LineNumberTable'}],
                              'code': '*\xb7\x00\x01\xb1',
                              'exception_table': [],
                              'max_locals': 1,
                              'max_stack': 1,
                              'name': 'Code'}],
              'descriptor_index': 8,
              'name_index': 7},
             {'access_flags': 9,
              'attributes': [{'attributes': [{'line_number_table': [{'line_number': 3,
                                                                     'start_pc': 0},
                                                                    {'line_number': 4,
                                                                     'start_pc': 8}],
                                              'name': 'LineNumberTable'}],
                              'code': '\xb2\x00\x02\x12\x03\xb6\x00\x04\xb1',
                              'exception_table': [],
                              'max_locals': 1,
                              'max_stack': 2,
                              'name': 'Code'}],
              'descriptor_index': 12,
              'name_index': 11}],
 'minor_version': 0,
 'super_class': 6,
 'this_class': 5}

出力結果例として,このJavaプログラムを使っています.

class Hello {
  public static void main(String[] args){
    System.out.println("Hello");
  }
}