【发布时间】:2015-12-08 02:56:27
【问题描述】:
我在加载 Spring XD 处理器模块类时遇到问题,想知道如何解决:
背景资料
我有一个 Spring XD 处理器模块,它在 Spring XD 容器中运行时找不到某些类。我遇到了 jaxb xml 转换和 xstream xml 转换的类加载问题,因为类加载器找不到用于转换 xml 的类。 jaxb 类在另一个 jar 文件中。 xstream 类在同一个(模块的)jar 文件中。无需任何 jaxb/xstream 代码即可轻松重现该问题(见下文)。
问题
只要下面的处理器模块代码在 Spring XD 容器中执行,类加载器就无法从模块的 jar 中找到任何类(我更改了这篇文章的包名。Foo 在同一个 jar 中的同一个包中文件。没有外部依赖项。):
// This is a spring xd processor
public class TestTransformer {
private final Logger logger = LoggerFactory.getLogger(getClass());
public String process(String input) {
try {
Class clazz = Class.forName("some.package.Foo", false, Thread.currentThread().getContextClassLoader());
logger.info("Class: {}", clazz.toString()); // works in test
} catch (ClassNotFoundException e) {
// happens when deployed to spring-xd container
logger.error(e.toString(), e);
throw new RuntimeException(e.toString(), e);
}
return input;
}
}
此代码在测试(单元测试和 Spring XD 集成测试)中有效,但在作为模块部署到 Spring XD(单节点)时失败。堆栈跟踪:
Caused by: java.lang.ClassNotFoundException: some.package.Foo
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:344)
at some.package.TestTransformer.process(TestTransformer.java:13)
... 88 more
我使用 Spring XD 1.2.0 和 1.2.1 验证了该行为。值得注意的是,处理器模块在使用反应器流时运行时没有任何类加载问题。
问题
我做错了什么,我该如何解决这个问题?
【问题讨论】:
-
您是说 some.package.Foo 在单独的 jar 文件中,例如 foo.jar 和 foo.jar 在您模块的类路径中?即,声明为依赖项并且 lib/foo.jar 包含在您的模块 uberjar 中?如果您的问题实际上与 jaxb 或 xstream 类有关,那就另当别论了。
-
不,这个例子中的所有类都在同一个包的同一个jar文件中。它与 jaxb 或 xstream 无关,因为我通过创建上面的示例来重现问题,删除了所有这些依赖项。
标签: spring classloader spring-xd