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

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

バックアップからのビルド検証ではまる

Java

バックアップからのビルド検証で、バックアップ物からビルドしたモノとリリース物が一致しないとなって、はまったのでメモ。

調査結果

調べてみたところ、「interfaceの定数として定義されたabstractメソッドを持つ列挙型」と「それを利用するクラス」がある場合、

とで、別のバイナリができあがるっぽい。次のようなサンプルで確認。


Interfaceの定数として定義されたabstractメソッドを持つ列挙型:

public interface X {
    enum Enum {
        A {
            void foo() {}
        };
        abstract void foo();
    }
}

それを利用するクラス:

public class AbstractEnumUse {
    public static void main( String[] args ) {
        System.out.println( X.Enum.A.toString() );
    }
}

ためした手順。

$ mkdir -p ../dir/a
$ mkdir -p ../dir/b
$ javac -d ../dir/a  AbstractEnumUse.java # ../dir/a に AbstractEnumUse.javaと依存クラスをコンパイル。
$ javac -d ../dir/b  AbstractEnumUse.java # ../dir/b に AbstractEnumUse.javaと依存クラスをコンパイル。
$ diff ../dir/a ../dir/b/ # diffで比較。同じなので何も出力されない。

$ rm -rf ../dir/b/AbstractEnumUse.class  # AbstractEnumUse.javaだけ削除して
$ javac -cp ../dir/b  -d ../dir/b  AbstractEnumUse.java # 列挙型は先にコンパイルしたものを利用して再コンパイル。
$ diff ../dir/a ../dir/b/ # diffで比較 → 違う!
バイナリー・ファイル../dir/a/AbstractEnumUse.classと../dir/b/AbstractEnumUse.classは違います
  • 列挙型のabstractメソッドを消したり、interfaceの定数として定義するのをやめれば、同じバイナリになる。
  • Eclipseのバイナリ比較ツールでみると、インナークラスへのaccess_flagsが違うらしいけど、よくわからん。



対策

  • 列挙型がabstractメソッドを持つ必要も、Interfaceの定数として定義される必要もないので、次のリリースまでに実装の方は直しておく。
  • 今回は・・、むー、どうしようかな。そもそも同じ手順でビルドしてるのに、何で違う結果になるのかわからん。「mvn clean」してるしなー。