interface A
class B implements A
我在将 B 转换为 A 时遇到 ClassCastException。A 和 B 都在同一个包中。
这可能是由于类加载器的原因。
为什么同一个包的类加载器会发生变化?
我该如何处理这个问题?
附加信息
- 接口A(即AdminService)和实现类B(即AdminServiceImpl)位于同一包(fusion-core)中,
- 而转换发生在不同的包中。
——选角并不是直接进行的。即 B b = new B(); A a = (A) b; 没有发生。
-
通过解析 OSGi 服务注册表中的服务来进行转换。即
AdminService adminService = getService(AdminService.class.getName(), 100);
公共T getService(字符串类型,长时间等待){
ServiceTracker serviceTracker = serviceRegistry.get(type);
if (serviceTracker == null) {
serviceTracker = this.registerServiceTracker(type);
}
T服务=空;
尝试 {
服务 = (T) serviceTracker.waitForService(timeToWait);
} catch (InterruptedException e) {
logger.error("获取服务时出错", e);
} 退货服务;
}
Epilog
谢谢 Ivan、Angelo 和 BJ。其实BJ的指点帮我解决了这个问题。
在尝试执行转换的包的清单中,
正在导出包含接口和实现的另一个包的包。因此,两个不同的类加载器可能会加载相同的字节代码。 Bundle(执行转换)可能假设该包是其自身的一部分并再次加载字节代码!
非常感谢大家。
interface A
class B implements A
I am getting ClassCastException in casting B to A. Both A and B are in the same bundle.
This could be because of the class loader.
Why is the class loader getting changed for the same bundle?
How can I handle this problem?
Additional information
- interface A (ie AdminService) and the implementation class B (ie AdminServiceImpl) are in the same package (fusion-core)
- Whereas the casting is happening in a different package.
--The casting is not happening directly. ie B b = new B(); A a = (A) b;
is not happening.
-
Casting is happening by resolving a service at OSGi service registry. ie
AdminService adminService = getService(AdminService.class.getName(), 100);
public T getService(String type, long timeToWait) {
ServiceTracker serviceTracker = serviceRegistry.get(type);
if (serviceTracker == null) {
serviceTracker = this.registerServiceTracker(type);
}
T service = null;
try {
service = (T) serviceTracker.waitForService(timeToWait);
} catch (InterruptedException e) {
logger.error("Error while fetching service", e);
} return service;
}
Epilog
Thank you Ivan, Angelo and BJ. Actually BJ's pointer helped me to fix the problem.
In the manifest of the bundle which was trying to perform the cast, <EXPORT-PACKAGE>
was exporting the package of the other bundle which contained the interface and the implementation. Because of this probably the same byte code was getting loaded by the two different class loaders. Bundle (performing the cast) probably assumed the package to be a part of itself and loaded the byte code again !!!
Thanks a lot guys.
发布评论
评论(1)
如果执行转换为 A 的代码加载了与定义 B 的包不同的 A(并且如您所述包含 A),则 VM 中可能有两个不同的 A 类。一个来自定义 B 的包,另一个由执行转换为 A 的包使用。
由于 A 是共享类型,因此您需要确保定义 B 的包和转换为 A 的包都使用相同的类 A。它们都应该从第三个包中导入包含 A 的包,或者定义 B 的包应该导出包含 A 的包,以便执行到 A 的转换的包可以导入该包。
If the code performing the cast to A has loaded a different A than the bundle which defined B (and contains A as you state), then there may be two different A classes in the VM. One from the bundle defining B and another one used by the bundle performing the cast to A.
Since A is a shared type, you need to make sure that the bundle defining B and the bundle casting to A are both using the same class A. They should both either import the package containing A from some 3rd bundle or the bundle defining B should export the package containing A so the bundle performing the cast to A can import that package.