【发布时间】:2019-05-11 18:00:22
【问题描述】:
我有一个使用自定义类路径调用 Java 11 类的 ANT 脚本
<path id="ant.classpath">
<fileset dir="${basedir}/lib/ant">
<include name="*.jar" />
</fileset>
</path>
<taskdef name="myTaskDef" classname="A.SomeClass" classpathref="ant.classpath" />
${basedir}/lib/ant 目录包含几个 jars
- A.jar - 我的图书馆
- B.jar - 第三方库
- C.jar - 第三方库,不同于 B.Jar 的公司
这些 jars 都加载到类路径 ${ant.classpath} 中就好了。
工作流程是这样的: A.jar 调用 B.jar,B.jar 调用 C.jar。
所以,A.jar 调用 B.jar 中的类没有问题。它使用 JAVA 中的 import 语句来调用类:
import B.SomeClass;
这很好用。
但是,B.jar 调用 C.jar 并失败。
我能够检查两个第三方库的源代码,并了解到 B.jar 使用 Java 的 Classloader 类从 C.jar 调用类。它不使用 import 语句。
下面是 B.jar 中一个类的代码
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
....
classLoader.loadClass("C.SomeClass");
我得到的例外是:
java.lang.ClassNotFoundException: C.SomeClass
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at B.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:122)
我能够验证 C.SomeClass 确实存在于 C.jar 中。
我怀疑它加载的类路径与 ant taskdef 提供的类路径不同。当我尝试使用 ClassLoader 从我的库 (A.jar) 中加载 C.jar 类时,我得到了同样的异常。但是导入效果很好。
我有点不知所措,因为我无法让 B.jar 通过 Ant 正确加载 C.jar。
编辑:
如果有用的话,我使用的是 Java 11,B.jar 实际上是 jaxb-api-2.4.0.jar (javax.xml.bind) 而 C.jar 是 jaxb-runtime-2.4.0。 jar (com.sun.xml.bind) 及其依赖项(jaxb-core、stax-ex、txw2 等)。当我打电话时,我得到了 ClassNotFoundException:
JAXBContext jc = JAXBContext.newInstance(Feature.class);
它找不到类 com.sun.xml.bind.v2.ContextFactory,我已经确认它确实存在。
【问题讨论】:
-
你是否在详细模式下运行过 ant?它应该向您展示所有 .jar 被加载到类路径中的内容。虽然这不是一个解决方案,但如果所有需要的 jar 都加载到类路径中,这将为您提供洞察力。此外,如果任何不需要的 jar 是类路径的一部分,可能会产生问题。