使用上下文加载器加载资源失败并出现 NullPointerException

Posted

技术标签:

【中文标题】使用上下文加载器加载资源失败并出现 NullPointerException【英文标题】:Loading Resources with the Context Loader fails with a NullPointerException 【发布时间】:2012-04-12 06:51:42 【问题描述】:

我只是想知道为什么我不能在 Felix OSGi 中使用线程上下文加载器加载资源?我不应该触摸上下文加载器,是我做错了什么还是一个错误?

我有一个带有简单 Activator 的超级简单的捆绑包:

public class Activator implements BundleActivator 
    public void start(BundleContext context) throws Exception 
        System.out.println("Hello World!!");
        String resourcePath = "META-INF/mySuperDuperResource.txt";

        // works
        System.out.println(Activator.class.getClassLoader().getResource(resourcePath));
        // null-pointer exception
        System.out.println(Thread.currentThread().getContextClassLoader().getResource(resourcePath));

    
    public void stop(BundleContext context) throws Exception 
        System.out.println("Goodbye World!!");
    

现在使用 Activator.class.getClassLoader 使用类加载器加载资源。但不是 Thread.currentThread().getContextClassLoader()。我得到了:

ERROR: Bundle info.gamlor.osgi [26] Unable to get module class path. (java.lang.NullPointerException)
java.lang.NullPointerException
        at org.apache.felix.framework.BundleRevisionImpl.calculateContentPath(BundleRevisionImpl.java:410)
        at org.apache.felix.framework.BundleRevisionImpl.initializeContentPath(BundleRevisionImpl.java:347)
        at org.apache.felix.framework.BundleRevisionImpl.getContentPath(BundleRevisionImpl.java:333)
        at org.apache.felix.framework.BundleRevisionImpl.getResourceLocal(BundleRevisionImpl.java:472)
        at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1432)
        at org.apache.felix.framework.BundleWiringImpl.getResourceByDelegation(BundleWiringImpl.java:1360)
        at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.getResource(BundleWiringImpl.java:2256)
        at info.gamlor.osgi.Activator.start(Activator.java:23)
        at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:641)
        at org.apache.felix.framework.Felix.activateBundle(Felix.java:1977)
        at org.apache.felix.framework.Felix.startBundle(Felix.java:1895)
        at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:944)
        ...
org.osgi.framework.BundleException: Activator start error in bundle info.gamlor.osgi [29].
        at org.apache.felix.framework.Felix.activateBundle(Felix.java:2027)
        at org.apache.felix.framework.Felix.startBundle(Felix.java:1895)
        at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:944)
        at org.apache.felix.gogo.command.Basic.start(Basic.java:729)
        ...
Caused by: java.lang.NullPointerException
        at org.apache.felix.framework.BundleRevisionImpl.getResourceLocal(BundleRevisionImpl.java:474)
        at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1432)
        at org.apache.felix.framework.BundleWiringImpl.getResourceByDelegation(BundleWiringImpl.java:1360)
        at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.getResource(BundleWiringImpl.java:2256)
        at info.gamlor.osgi.Activator.start(Activator.java:23)
        at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:641)
        at org.apache.felix.framework.Felix.activateBundle(Felix.java:1977)
        ... 32 more

现在只要设置线程上下文类加载器就可以了:

Thread.currentThread().setContextClassLoader(Activator.class.getClassLoader());

但这有一种骇人听闻的感觉。感觉以后会咬我的。

【问题讨论】:

【参考方案1】:

我不确定为什么会发生这种情况让您感到惊讶。默认情况下,线程的上下文类加载器设置为其父级的类加载器,一开始就设置为系统类加载器。所以,假设你没有做任何特殊的事情,上下文类加载器是系统类加载器,它与你的包的类加载器不同,因此它找不到你的资源。

我同意设置上下文类加载器有一种 hacky 的感觉,但有些库需要这样做。我会做类似的事情,

ClassLoader previous = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
badlyBehavedLibraryCall();
Thread.currentThread().setContextClassLoader(previous);

【讨论】:

我对这个奇怪的异常感到惊讶。如果资源不可见,通常你会得到一个空值。好的,所以我将保留我的类加载器设置。当然在 try-finally 中设置它。

以上是关于使用上下文加载器加载资源失败并出现 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章

Karma/Jasmine 测试失败并出现错误:'未捕获的错误:尚未为上下文加载模块名称“simple_test.js”:_。使用要求([])'

WPF 资源加载在 LoadFrom 加载上下文中失败

duilib加载资源文件失败 每次开机都会出现这个

两种类别的类加载器

在 HikariConfig 类加载器或线程上下文类加载器中加载驱动程序类 com.mysql.cj.jdbc.Driver 失败

应用程序加载器使用 Signiant 成功,但使用 DAV 失败