迭代ClassLoader.getResources()的结果时出现奇怪的NPE

时间:2014-05-14 09:30:32

标签: java nullpointerexception classloader

我认为以下代码是安全的,但是我在调​​用hasMoreElements()时获得了NPE。什么想法可能是错的?

我应该补充一点,我在Windows上使用Java 1.7.0_55-b13,64位。

final List<URL> urls = new ArrayList<URL>();
final String plUri = "META-INF/plugin.xml";
Enumeration<URL> urlsEn =
   Thread.currentThread().getContextClassLoader().getResources(pluginsUri);
if (urlsEn != null) {
  while (urlsEn.hasMoreElements()) {  //  NPE happens here
    final URL u = urlsEn.nextElement();
    urls.add(u);
  }
}

堆栈追踪:

java.lang.NullPointerException
    at sun.misc.MetaIndex.mayContain(MetaIndex.java:243)
    at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:830)
    at sun.misc.URLClassPath$2.next(URLClassPath.java:273)
    at sun.misc.URLClassPath$2.hasMoreElements(URLClassPath.java:283)
    at java.lang.ClassLoader$2.hasMoreElements(ClassLoader.java:1322)
    at sun.misc.CompoundEnumeration.next(CompoundEnumeration.java:45)
    at sun.misc.CompoundEnumeration.hasMoreElements(CompoundEnumeration.java:54)
    at sun.misc.CompoundEnumeration.next(CompoundEnumeration.java:45)
    at sun.misc.CompoundEnumeration.hasMoreElements(CompoundEnumeration.java:54)
    at com.github.jochen.afw.core.guice.GuiceComponentFactoryBuilder.getComponentUrls(GuiceComponentFactoryBuilder.java:256)
    at com.github.jochen.afw.core.guice.GuiceComponentFactoryBuilder.build(GuiceComponentFactoryBuilder.java:160)
    at com.github.jochen.afw.core.guice.GuiceComponentFactoryBuilderTest.testSuccessfullConfiguration(GuiceComponentFactoryBuilderTest.java:20)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    ....

1 个答案:

答案 0 :(得分:1)

我讨厌建议你的问题很简单,但pluginsUri可以null在这里吗?至少在您的代码段中,您创建了一个plUri变量,但随后将未提及的pluginsUri传递给ClassLoader.getResources()

从堆栈跟踪中,搜索“URLClassPath空指针异常”未覆盖this question,它看起来是相同的堆栈跟踪。在他们的例子中,getResources()的论证显然是空的。

查看Java 7 codebase,我们看到MetaIndex:243是:

if (entry.startsWith(conts[i])) {

此行entry可能是null。在向上看堆栈时,entry看起来是您传递给name的{​​{1}}参数。

SSCCE

ClassLoader.getResources()

复制堆栈跟踪(在Java 8中,不能少):

public class ClassLoaderNPE {
  public static void main(String[] args) throws IOException {
      Enumeration<URL> urls = ClassLoader.getSystemClassLoader().getResources(null);
      System.out.println(urls.hasMoreElements());
  }
}

如果$ java -version java version "1.8.0_45" Java(TM) SE Runtime Environment (build 1.8.0_45-b15) Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode) $ java -cp . ClassLoaderNPE Exception in thread "main" java.lang.NullPointerException at sun.misc.MetaIndex.mayContain(MetaIndex.java:242) at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:995) at sun.misc.URLClassPath$2.next(URLClassPath.java:288) at sun.misc.URLClassPath$2.hasMoreElements(URLClassPath.java:298) at java.lang.ClassLoader$2.hasMoreElements(ClassLoader.java:1278) at sun.misc.CompoundEnumeration.next(CompoundEnumeration.java:45) at sun.misc.CompoundEnumeration.hasMoreElements(CompoundEnumeration.java:54) at sun.misc.CompoundEnumeration.next(CompoundEnumeration.java:45) at sun.misc.CompoundEnumeration.hasMoreElements(CompoundEnumeration.java:54) at ClassLoaderNPE.main(ClassLoaderNPE.java:9) nameJDK似乎未指定会发生什么。我提交了一个错误建议修复此行为,或者至少澄清文档。如果/当Oracle接受此问题,我会更新此帖子。

更新:报告被跟踪为JDK-8136831,并已在Java 9中修复。