没有 includeantruntime 的 ant LinkageError

ant LinkageError without includeantruntime

如何防止 AntClassLoader 和 URLClassLoader 导致链接错误?

由于一个较旧的项目,junit 和 hamcrest.core 被放入 ANT_HOME 并且我们的构建使用 includeant运行time=true 以便 运行 单元测试。

我现在正在开发一个用 ant 构建的项目,我不想依赖 ANT_HOME 中的任何 jar 文件。我虔诚地在所有 javac 节中使用了 includeant运行time=false。

但是,现在我正在使用 hamcrest 进行测试,我收到 运行时间链接错误。

java.lang.LinkageError: loader constraint violation: when resolving method 
"org.junit.Assert.assertThat(Ljava/lang/Object;Lorg/hamcrest/Matcher;)V" 
the class loader (instance of org/apache/tools/ant/loader/AntClassLoader5) 
of the current class, myclass, and the class loader (instance of
java/net/URLClassLoader) for resolved class, org/junit/Assert, have different
Class objects for the type assertThat used in the signature

junit 运行测试时发生 运行时间链接错误。

我好像有两个选择,我都不喜欢:

  1. 从 ANT_HOME 中删除 junit 和 hamcrest.core。这打破了另一个 项目。
  2. 从项目中删除junit和hamcrest.core并依赖 ANT_HOME 中的设置。这是我要避免的。

我原以为包含运行时间会有所帮助。

我的目标是让 junit 和 hamcrest.core 保留在 ANT_HOME 中,同时也将它们包含在项目中。也就是说,ANT_HOME的内容应该无关紧要。

这个问题有解决办法吗?

设置"includeantruntime=false"是好事。它迫使你的构建更加独立,更少依赖于本地机器的配置,我喜欢将这个问题称为 "magic build server"(没有人真正知道它是如何工作的)

我使用 Apache ivy 来管理我的 ANT 类路径依赖项。下面给出了在本地 "lib" 目录中使用 jars 的示例:

  • sample example which explain how to use filesystem resolver

ivy 的真正威力在于将它与 Maven 存储库结合使用。您的源代码保持可移植性,但不必随所有第 3 方 jar 一起提供。起初它看起来令人生畏,但它是一种值得研究的方法。 Maven 做对了一些事情 :-)

希望对您有所帮助。

解决这个问题有两个步骤:

  1. <pathelement path="${java.class.path}" /> 添加到测试环境的 class 路径。
  2. fork="true" 添加到 junit 元素的属性中。您还可以为 junit 元素选择分叉模式。例如,我使用 forkmode="once".
对于所有条件,

includeantruntime 应保持 false

允许 junit 分叉明确地将 junit class 加载程序与 ant class 加载程序分开,以防止任何无意的关联。需要 java.class.path 来明确允许 ant 找到执行所需的所有 classes。

通过这些设置,ant lib 目录中的库不会被使用,也不会干扰 JUnit 测试。