没有 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 运行测试时发生 运行时间链接错误。
我好像有两个选择,我都不喜欢:
- 从 ANT_HOME 中删除 junit 和 hamcrest.core。这打破了另一个
项目。
- 从项目中删除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 做对了一些事情 :-)
希望对您有所帮助。
解决这个问题有两个步骤:
- 将
<pathelement path="${java.class.path}" />
添加到测试环境的 class 路径。
- 将
fork="true"
添加到 junit 元素的属性中。您还可以为 junit 元素选择分叉模式。例如,我使用 forkmode="once"
.
对于所有条件,includeantruntime
应保持 false
。
允许 junit 分叉明确地将 junit class 加载程序与 ant class 加载程序分开,以防止任何无意的关联。需要 java.class.path 来明确允许 ant 找到执行所需的所有 classes。
通过这些设置,ant lib 目录中的库不会被使用,也不会干扰 JUnit 测试。
如何防止 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 运行测试时发生 运行时间链接错误。
我好像有两个选择,我都不喜欢:
- 从 ANT_HOME 中删除 junit 和 hamcrest.core。这打破了另一个 项目。
- 从项目中删除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 做对了一些事情 :-)
希望对您有所帮助。
解决这个问题有两个步骤:
- 将
<pathelement path="${java.class.path}" />
添加到测试环境的 class 路径。 - 将
fork="true"
添加到 junit 元素的属性中。您还可以为 junit 元素选择分叉模式。例如,我使用forkmode="once"
.
includeantruntime
应保持 false
。
允许 junit 分叉明确地将 junit class 加载程序与 ant class 加载程序分开,以防止任何无意的关联。需要 java.class.path 来明确允许 ant 找到执行所需的所有 classes。
通过这些设置,ant lib 目录中的库不会被使用,也不会干扰 JUnit 测试。