执行Java程序时遇到一个IncompatibleClassChangeError异常。 IncompatibleClassChangeError的javadoc是这么说的,

Thrown when an incompatible class change has occurred to some class definition. The definition of some class, on which the currently executing method depends, has since changed.

意思是Java程序在执行时发现类的定义发生了变化。

通常,如果编译时依赖的类定义和运行时依赖的类定义不一致就有可能抛出这种异常。

比如,有如下程序,

 public class ChildType extends BaseType {
 }

在编译时,BaseType是一个类,编译顺利通过。 在运行时,classpath里的BaseType如果是一个接口,就会在运行时抛出IncompatibleClassChangeError异常。

其它会抛出IncompatibleClassChangeError异常的场景有,

  • implements a class
  • 静态成员变成非静态成员
  • 非静态成员变成了静态成员

我的Java程序抛出IncompatibleClassChangeError异常的原因是运行时的classpath里同时存在不同版本Guava jar包。 在一个早期的Guava版本里,Ticker是一个接口(且这个Ticker定义更早地在运行时被加载); 在另一个较新的Guava版本里,Ticker变成了一个类,并有其它代码extends Ticker。 所以在运行到新版本的Guava代码时,就会抛出异常。

另外,升级库版本时,为了防止运行时抛出IncompatibleClassChangeError异常,最好针对新的库重新编译程序 (这样编译时就能发现错误); 而不是简单替换库的jar包。