読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

Javaクラス解析機を作る 5日目

属性の読み込みに着手。クラス属性を読み込む部分を書いて、次の2つの属性の読み込みに対応。

  • 定数値(ConstantValue)
  • ソースファイル(SourceFile)

あと、いろいろリファクタしました。

  • 長くなってきたのでファイルを分割して、クラス構成も大幅変更。
  • ClassとかConstantのコンストラクタでIOからデータを読み込むのをやめ、専用の関数で読むようにした。

現在の読み込み対応データ

★付きが今日対応したモノ。

クラスデータ
名称 サイズ 説明
magic 4byte クラスファイルを識別するためのマジックナンバー。0xCAFEBABEが入る。
minor_version 2byte クラスのマイナーバージョン
major_version 2byte クラスのメジャーバージョン
constant_pool_count 2byte constant_pool (クラス名メソッド名などの定数が格納されるテーブル)の数
constant_pool 可変 クラス名メソッド名などの定数が格納されるテーブル。constant_pool_count-(1+Double or Longのconstantの数)個のconstant_poolが並ぶ。「文字列」や「Class情報」など種類がいくつかあって、それぞれデータ形式/サイズが異なる。
access_flags 2byte クラス/インターフェイスのアクセス権限情報
this_class 2byte このクラスファイルで定義されているクラスを示すconstant_poolのid。
super_class 2byte このクラスファイルで定義されているクラスの親クラスを示すconstant_poolのid。
interfaces_count 2byte 実装しているインターフェイスの数。
interfaces 可変(2byte*interfaces_count) 実装しているインターフェイスを示すconstant_poolのid。interfaces_count数だけ続く。
fields_count 2byte クラス/インターフェイスで定義されているフィールドの数。
field_info 可変 クラス/インターフェイスで定義されているフィールド。データ形式は「フィールドデータ」を参照。fields_count数だけ続く。
methods_count 2byte クラス/インターフェイスで定義されているメソッドの数。
method_info 可変 クラス/インターフェイスで定義されているメソッドデータ形式は「メソッドデータ」を参照。methods_count数だけ続く。
★attributes_count 2byte クラス/インターフェイスの属性の数。
★attribute_info 可変 クラス/インターフェイスの属性。コンパイル元のソースファイルの情報などが含まれる。データ形式は各種「属性」を参照。methods_count数だけ続く。
フィールドデータ
名称 サイズ 説明
access_flags 2byte フィールドのアクセス権限情報
name_index 2byte フィールド名を示すconstant_poolのid
descriptor_index 2byte フィールドの型の文字列表現を示すconstant_poolのid
attributes_count 2byte フィールドに付加された属性の数
attribute_info 可変 フィールドの属性。定数の値やdeplicatedの情報なんかが属性として指定される。attributes_count数だけ続く
メソッドデータ
名称 サイズ 説明
access_flags 2byte メソッドのアクセス権限情報
name_index 2byte メソッド名を示すconstant_poolのid
descriptor_index 2byte メソッドの引数と戻り値の型の文字列表現を示すconstant_poolのid。「(<引き数の型><引き数の型>..)<戻り値の型>」形式。
attributes_count 2byte メソッドに付加された属性の数
attribute_info 可変 メソッドの属性。メソッドの処理コード、発生する例外などが属性として指定される。attributes_count数だけ続く
ConstantValue属性

文字列とプリミティブ型の定数の値を示す、フィールドの属性。

名称 サイズ 説明
★attribute_name_index 2byte 属性名"ConstantValue"を示すconstant_poolのid。
★attribute_length 4byte 属性値の長さ。2で固定
★constantvalue_index 2byte 定数値を示すconstant_poolのid。
SourceFile属性

クラスのコンパイル前のソースファイル名(パスではない。)の情報を保持する、クラス属性。

名称 サイズ 説明
★attribute_name_index 2byte 属性名"SourceFile"を示すconstant_poolのid。
★attribute_length 4byte 属性値の長さ。2で固定
★sourcefile_index 2byte ソースファイル名を示すconstant_poolのid。

ここまでの解析コード

zipにしました。
→Javaクラス解析機 080414

動作サンプル

解析対象のJavaクラス(のソース)

package com.example;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public interface Constants
extends Serializable {

    static final String stringConstant = "aaa";
    static int intConstant = 1;
    public static long longConstant = 100L;
    public static final List<String> listConstant = new ArrayList<String>();

}

解析!

require "javaclass"

open( "./Constants.class", "r+b" ) {|io|
  jc = JavaClass.from io
  puts jc.to_s
}

実行結果です。

// version 49.0
// source Constants.java
public abstract interface com.example.Constants 
extends java.lang.Object 
implements java.io.Serializable {

    public static final java.lang.String stringConstant = "aaa";
    public static final int intConstant = 1;
    public static final long longConstant = 100L;
    public static final java.util.List listConstant;

    static void <clinit> (  ) {};

}

オブジェクト型の定数はConstantValue属性で保持されない様子。「」とかいう関数が勝手に追加されているので、この中で初期化してるっぽいな。