java.lang.IncompatibleClassChangeErrorの原因
たまにIncompatibleClassChangeErrorで私のブログにきてる人がいたみたいなのでその理由を書いてみようと思いました。
このエントリーはまともな原因を昔書かなかったことへの申し訳なさからきています。
たぶんさまざまな原因があるのでしょうが、
2種類ほど確実におこるケースがあったので書きます。
privateではなく、かつnon-staticなフィールドが、
staticに変わっていたら発生します。
またその逆もしかりです。
これはJLSに書いてあります。
non-staticをstaticに変えてみて確かにjava.lang.IncompatibleClassChangeErrorが発生しました。
Exception in thread "main" java.lang.IncompatibleClassChangeError: Expected non-static field B.field at A.main(A.java:6)
メソッドも同様らしいです。
non-staticをstaticなメソッドに変更してみたらjava.lang.IncompatibleClassChangeErrorが発生しました。
Exception in thread "main" java.lang.IncompatibleClassChangeError: Expecting non-static method B.getB()Ljava/lang/String; at A.main(A.java:6)
これらは依存するJarが変更されたことによって引き起こされることがほとんどでしょう。
getfieldとgetstatic
Callerのクラスファイルではgetfieldで呼んでいるのに、
相手側のフィールドがstaticに変更されていたことにより、
Callerは本来getstaticで呼び出さないといけない状態になっているため
互換性が失われた状態です。
invokevirtualとinvokestatic
メソッドの場合も同じ理屈です。
Caller側のクラスがいる方のJarを再コンパイルすることで解決します。
ただし、コンパイル時には相手側のJarは最新のものを使う必要があります。