2

我正在努力将大型代码库从一个 API 版本移植到另一个版本(特别是 Hadoop CDH3 到 Hadoop CDH4)。

在这些库的“升级”过程中,有人决定将常用的具体类(JobContext)更改为接口,并将其所有功能移动到子类(JobContextImpl)中。通常,这将是一个相当直截了当的提议。但是,我们仍然需要保持对旧版本库的支持,从而支持作为具体和接口的类。

我们显然可以有 2 组不同的 jars,我们可以根据我们使用的 hadoop 版本交换它们,但这会给我们带来很多不必要的头痛。我想创建一个可以针对两个 hadoop 版本运行的版本。

当然,工厂模式会首先出现在您的脑海中,但问题是新版本中的实现类在以前的版本中不存在,因此代码只会针对一组库进行编译时间,只对一个。

接下来,我尝试使用 groovyscript 和一些巧妙的反射来检测类路径中的库版本。我可以实例化这些对象,但使用我没有编译的库之一给了我:

IncompatibleClassChangeError:找到接口 org.pain.MyContext,但应使用类

编辑: 总之,我需要能够实例化一个可以是具体类或接口的类。我可以检测到它是哪一个,如果它是一个接口,我知道实现在哪里,但如果是具体的,那么该实现类不存在。

4

1 回答 1

1

没有办法让 JVM 忽略二进制不兼容;即同一类型的矛盾定义。

可能解决这个问题,但它会非常尴尬。

你需要做的是:

  • JobContext从源代码中消除对类的所有直接和间接引用,
  • 将所有类型的变量替换JobContextObject
  • 使用您使用. JobContext_Class<?>JobContextClass.forName(...)

简而言之,如果您可以摆脱代码使用或依赖于静态加载的所有地方JobContext,那么您将不会得到IncompatibleClassChangeError该类的任何异常。


老实说,我认为你最好只针对两个 Hadoop API 分别编译你的代码库。

于 2013-06-08T11:53:10.143 回答