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

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

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

例外とインナークラス属性に対応。

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

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

クラスデータ
名称 サイズ 説明
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。
Exceptions属性

発生しうる例外を示すメソッドの属性。

名称 サイズ 説明
★attribute_name_index 2byte 属性名"Exceptions"を示すconstant_poolのid。
★attribute_length 4byte 属性値の長さ。
★number_of_exceptions 2byte 例外の数。
★exception_index_table 可変(2byte*number_of_exceptions) 例外を示すconstant_poolのid。number_of_exceptions数だけ続く。
InnerClasses属性

クラス/インターフェイスで定義されたインナークラスの情報が記録されるクラス属性。メソッド内クラスもクラスのインナークラスとしてこの属性で保持される。

名称 サイズ 説明
★attribute_name_index 2byte 属性名"InnerClasses"を示すconstant_poolのid。
★attribute_length 4byte 属性値の長さ。
★number_of_classes 2byte インナークラスの数。
★classes 可変(8byte*number_of_classes) インナークラスの情報。データ形式は各種↓を参照。number_of_classes数だけ続く。

classes内のデータ

名称 サイズ 説明
★inner_class_info_index 2byte インナークラスを示すconstant_poolのid。
★outer_class_info_index 2byte インナークラスを持つクラス?を示すconstant_poolのid。無名クラスの場合、0になる。
★inner_name_index 2byte インナークラスの名前を示すconstant_poolのid。無名クラスの場合、0になる。
★inner_class_access_flags 2byte インナークラスのアクセス権情報

ここまでの解析コード

→Javaクラス解析機 080415

動作サンプル

解析対象のJavaクラス(のソース)。インナークラスを持つ、インターフェイスとクラスを用意。

package com.example;
import java.util.Map;

/**
 * インナークラスを持つインターフェイス
 */
public interface InnerClass {

    // staticなインナークラス
    static class StaticInnerClass {
        // インナークラス内インナークラス
        static class StaticInnerInnerClass{}
        class InnerInnerClass{}
    }

    // インナークラス
    class BasicInnerClass {}

    // 匿名クラス
    Object x = new Object() {
        public String toString() { return "x"; }
    };

}
package com.example;
import java.util.Map;

/**
 * インナークラスを持つクラス
 */
public class InnerClassImpl
implements InnerClass {

    // staticなインナークラス
    static class StaticInnerClass2 {}

    // インナークラス
    class BasicInnerClass2 {}

    // 匿名クラス
    Object xx = new Object() {
        public String toString() { return "xx"; }
    };

    public static void main() {

        // 関数内クラス
        class MethodInnerClass {}

        // 関数内の匿名クラス
        Object yy = new Object() {
            public String toString() { return "yy"; }
        };
    }
}

あと、例外をスローする関数を持つやつも。

package com.example;

import java.io.IOException;

/**
 * 例外を投げる
 */
public class ThrowsException {
    public static void main ( String[] args )
    throws IOException, IllegalArgumentException, OutOfMemoryError {}

}

↑をまとめて解析!

require "javaclass"

[
  "./java_class/com/example/InnerClass.class",
  "./java_class/com/example/InnerClassImpl.class",
  "./java_class/com/example/InnerClass$StaticInnerClass.class",
  "./java_class/com/example/ThrowsException.class"
].each { |c|
  open( c, "r+b" ) {|io|
    jc = JavaClass.from io
    puts jc.to_s
    puts ""
  }
}

実行結果です。インナークラスは「// use inner ....」で始まるコメントとして、クラスの先頭に出力してみました。

// version 49.0
// source InnerClass.java
public abstract interface com.example.InnerClass 
extends java.lang.Object {

    // use inner public static class com.example.InnerClass$StaticInnerClass
    // use inner public static class com.example.InnerClass$BasicInnerClass
    // use inner class com.example.InnerClass$1

    public static final java.lang.Object x;

    static void <clinit> (  ) {};

}

// version 49.0
// source InnerClassImpl.java
public class com.example.InnerClassImpl 
extends java.lang.Object 
implements com.example.InnerClass {

    // use inner static class com.example.InnerClassImpl$StaticInnerClass2
    // use inner class com.example.InnerClassImpl$BasicInnerClass2
    // use inner class com.example.InnerClassImpl$1
    // use inner class com.example.InnerClassImpl$1MethodInnerClass
    // use inner class com.example.InnerClassImpl$2

    java.lang.Object xx;

    public void <init> (  ) {};
    public static void main (  ) {};

}

// version 49.0
// source InnerClass.java
public class com.example.InnerClass$StaticInnerClass 
extends java.lang.Object {

    // use inner public static class com.example.InnerClass$StaticInnerClass
    // use inner static class com.example.InnerClass$StaticInnerClass$StaticInnerInnerClass
    // use inner class com.example.InnerClass$StaticInnerClass$InnerInnerClass


    public void <init> (  ) {};

}

// version 49.0
// source ThrowsException.java
public class com.example.ThrowsException 
extends java.lang.Object {


    public void <init> (  ) {};
    public static void main ( java.lang.String[] arg1 )
    throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.OutOfMemoryError {};

}