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"); } }