使用上下文加载器加载资源失败并出现 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”:_。使用要求([])'
在 HikariConfig 类加载器或线程上下文类加载器中加载驱动程序类 com.mysql.cj.jdbc.Driver 失败