在一个 Eclipse 插件项目中,我有一个 jar 文件,我想从中加载类和调用方法。这些 jars 添加到清单文件的捆绑类路径中。如何加载这些类运行时,如果我尝试使用 urlclassloader 我得到 java.lang.NoClassDefFoundError 但我确定类在那里。我阅读了基于 Eclipse osgi 并使用它自己的类加载器,因此我可能会收到此错误。但为什么 ?有人对我的问题有很好的解释和实用的解决方案吗?谢谢你。
2 回答
这是由 OSGi 的不同类加载机制引起的问题。首先,检查您是否在清单中添加了正确的导入声明。如果导入是正确的(并且具有正确的版本),它们可能不可见,因为您使用的 JAR 没有导出所需的类。OSGi 只能看到导出的类。使用 Eclipse,这意味着您使用 Equinox 作为 OSGi 实现,您可能会使用 Eclipse-Buddy-Classloading。使用 JAR 创建一个新项目并导出所有内容。现在将它注册为你的主包的伙伴 - 主包现在可以看到提供包的每个类。
请记住,在 OSGi 中使用类加载器是“邪恶的”。类不能再通过其完全限定的类名来标识。
查看 OSGi 核心规范以获取有关 OSGi 类加载 (osgi.org) 和http://rajakannappan.blogspot.de/2010/03/eclipse-classloading-and-buddy-policy.html的更多信息
我遇到了类似的问题,这是我的解决方案。可能有点晚了,但我希望它能帮助其他有同样问题的人。
我注意到来自 eclipse (osgi) 的类加载器不会加载完整的 jar。它只加载通过直接加载的类classloader.load(classname)
。所以我只是用这个问题的代码读取了 jar 中包含的所有类名,并通过调用显式遍历所有类名classloader.load(classname)
。这是我管理它的方式的示例:
private void loadClasses(final File jar) {
final URL url = new URL("jar", "", "file:" + jar.getAbsolutePath() + "!/");
final List<String> classNames = getAllClassNames(jar); //Code from above link in this method
final URLClassLoader classloader = new URLClassloader(url, this.getClass().getClassLoader());
for (String className : classNames) {
classLoader.load(className);
}
}
如果你想实例化一个类,你可以这样做
final Class<?> clazz = classLoader.load(className);
final T type = (T)clazz.newInstance();
希望这可以帮助。