きどたかのブログ

いつか誰かがこのブログからトラブルを解決しますように。

java.lang.IncompatibleClassChangeErrorの原因

たまにIncompatibleClassChangeErrorで私のブログにきてる人がいたみたいなのでその理由を書いてみようと思いました。

このエントリーはまともな原因を昔書かなかったことへの申し訳なさからきています。

 

たぶんさまざまな原因があるのでしょうが、

2種類ほど確実におこるケースがあったので書きます。

 

privateではなく、かつnon-staticなフィールドが、

staticに変わっていたら発生します。

またその逆もしかりです。

 

これはJLSに書いてあります。

13.4.10 static Fields 

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)

 

メソッドも同様らしいです。

13.4.19 static Methods

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は最新のものを使う必要があります。