osgi - ClassLoader只在特定的Threads中查找Resource

标签 osgi classloader executorservice jbehave rft

我正在努力应对 ClassLoader 试图解析资源的情况,该资源只能在特定条件下工作。

用例如下:我将 IBM Rational Functional Tester 与 JBehave 结合用于自动验收测试。 JBehave 将测试指定为纯文本故事文件。这些故事文件可以引用其他故事文件,因此称为“Given Stories”。 JBehave 使用 ExecutorService执行故事可能是多线程的。虽然 JBehave 加载文本文件没有问题(使用 ClassLoader.getResourceAsStream),但它无法在从 ExecutorService 启动的线程中找到相同的文件。

运行中的类加载器是 ContextFinder .在调试应用程序并暂停两个线程时,最初启动 JBehave 的“主线程”和从执行程序服务启动以运行故事文件的“故事线程”,我可以识别出类加载器的实例是相同的。还有 parent 的实例等。

但是调用

Thread.currentThread().getContextClassLoader().getResource("HelloWorld.story")

在主线程中完美运行,在故事线程中失败并返回 null。

从 ContextFinder 的源代码来看,除了为堆栈上的类收集所有 ClassLoader 之外,它似乎几乎没有做其他事情。所以我尝试了这个:

SomeClass.class.getClass().getClassLoader().getResource("HelloWorld.story")

...结果相同。

这对我来说太奇怪了。感谢任何用于调试或缓解为什么显示此行为的指针!

最佳答案

线程上下文类加载器 (TCCL) 在 OSGi 中基本上是未定义的。您应该避免使用它。

作为标准 OSGi 的扩展,Equinox 确实提供了称为 ContextFinder 的东西,它执行堆栈检查以尝试在调用堆栈中找到最顶层的 OSGi 包类加载器。然而,您几乎无法控制,而且如您所见,结果可能出乎意料。当然,由于这是一个特定于 Equinox 的扩展,任何依赖 ContextFinder 正常工作的代码都将在所有其他 OSGi 框架上失败。

因此,与其浪费时间调试它,不如根本不使用 TCCL。如果要加载与特定类相关的资源,则从文字类对象执行,例如:

MyClass.class.getResource("HelloWorld.story");

更新:

我在您原来的问题中注意到了这一点:SomeClass.class.getClass()。其结果将是 java.lang.Class 本身的类对象。调用 getClassLoader()总是返回 JVM 引导类加载器....可能不是您想要的!

关于osgi - ClassLoader只在特定的Threads中查找Resource,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16019502/

相关文章:

java - 没有指定 bundle

java - 使用 ThreadPoolExecutor 检查服务器端口是否打开时,Android 应用程序挂起并显示黑屏 5-6 秒

java - 如何对java中ExecutorService内部的相似线程求和?

java - OSGI 服务异常行为

java - 如何从 OSGi 中的特定 bundle 版本添加导入包

java - MyClass.class.getClassLoader().getResource ("").getPath() 抛出 NullPointerException

java - 是什么导致了 java.lang.InternalError(它扩展了 VirtualMachineError)

java - java中模拟OS进程/抢占式线程停止/classloader+线程进程模拟

java - 生产者消费者主线程退出,而其他线程正在运行

java - 如何使用 BundleContext 从包 list 中获取属性值?