如何解决OSGI - 如何解决:ClassNotFoundException? (org.eclipse.osgi.internal.loader.BundleLoader.findClass)
当使用三个包时 A = first.bundle B = second.bundle 和 C = third.bundle,其中 A 依赖于 B和C,C在调用方法java.lang.Class.forName
时找不到B的类是否有任何 pom.xml 文件中缺少配置或以任何其他方式为 bunlde C 的 ClassLoader 配备类 B.SecondClass?
org.example.first.bundle.FirstClass
public void topLevelMethod() {
ThirdClass thirdObject = new ThirdClass();
thirdObject.resolveTheClassName("org.example.second.bundle.SecondClass")
}
org.example.third.bundle.ThirdClass
public <T> Class<T> resolveTheClassName(String className) throws ClassNotFoundException {
return (Class<T>) Class.forName(className);
}
java.lang.ClassNotFoundException: org.example.second.bundle.SecondClass 在 org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:516) 处不能被第三个.bundle_1.0.0.SNAPSHOT 找到 在 org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:171) 在 java.lang.ClassLoader.loadClass(ClassLoader.java:357) 在 java.lang.Class.forName0(Native Method) 在 java.lang.Class.forName(Class.java:264) 在 org.example.third.bundle.ThirdClassA.getContentType(ThirdClassA.java:100) 在 org.example.third.bundle.ThirdClassB$ReceivingTask.run(ThirdClassB.java:135) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 在 java.lang.Thread.run(Thread.java:748)
first.bundle/pom.xml
<dependencies>
<groupId>${project.groupId}</groupId>
<artifactId>second.package</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
<groupId>${project.groupId}</groupId>
<artifactId>third.package</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependencies>
second.bundle/pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.name}</Bundle-SymbolicName>
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
<Embed-Directory>OSGI-INF/lib</Embed-Directory>
<Embed-Transitive>true</Embed-Transitive>
<Import-Package>
*;resolution:=optional
</Import-Package>
<Export-Package>
org.example.second.bundle
</Export-Packlage>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
third.bundle/pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.name}</Bundle-SymbolicName>
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
<Embed-Directory>OSGI-INF/lib</Embed-Directory>
<Embed-Transitive>true</Embed-Transitive>
<Import-Package>
*;resolution:=optional
</Import-Package>
<Export-Package>
org.example.third.bundle
</Export-Packlage>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
解决方法
类加载器配置在一个图形中,每个导入的包都有边。因此,如果 C 在 B 中没有一个包的导入边,那么 C 就不能从 B 中的那个包中加载一个类。
如果 C 有来自 B 的对象,它可以在 Class.forName 调用中使用来自 B 的对象的类的类加载器。但通常不应在 OSGi 中使用 Class.forName。最好使用 OSGi 服务。然后 C 可以在 OSGi 服务注册表中定位感兴趣的对象。
,找到了解决方案!
public <T> Class<T> resolveTheClassName(String className) throws ClassNotFoundException {
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
List<Class<?>> foundClasses = findClass(bundleContext,serializedContentType);
if(foundClasses.isEmpty()) {
return (Class<T>)Class.forName(serializedContentType);
} else {
return (Class<T>)foundClasses.get(0);
}
}
private List<Class<?>> findClass(BundleContext context,String name) {
List<Class<?>> result = new ArrayList<Class<?>>();
for (Bundle b : context.getBundles()) {
try {
Class<?> c = b.loadClass(name);
result.add(c);
} catch (ClassNotFoundException e) {
// No problem,this bundle doesn't have the class
}
}
return result;
}
How to load a class by classname string from OSGi runtime environment?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。