如何在不知道Java 9中jar文件的包名称或文件系统路径的情况下列出所有资源

时间:2017-11-14 00:57:05

标签: resources classloader java-9

Java 7中的

& 8我用来做

URLClassLoader urlLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
for (URL u : urlLoader.getURLs()) {
    System.out.println("*************** url=" + url);
}

但是在Java 9中,上面给出了错误

java.lang.ClassCastException: java.base/jdk.internal.loader.ClassLoaders$AppClassLoader cannot be cast to java.base/java.net.URLClass
Loader

那么如何在不知道jar文件的包前缀或文件系统路径的情况下列出所有资源?

3 个答案:

答案 0 :(得分:1)

Java9 Release Note说明了这一点:

  

应用程序类加载器不再是实例   java.net.URLClassLoader(一个从未实现的实现细节   在以前的版本中指定)。假设的代码   ClassLoader.getSytemClassLoader()会返回URLClassLoader个对象   需要更新。请注意,Java SE和JDK不提供   用于动态扩充类的应用程序或库的API   在运行时的路径。

add to this from the mailing list,资源查找方法很少,包括以下方式:

  • 命名模块中的类可以通过Class::getResourceAsStream方法读取自己的资源,该方法返回InputStream。它可以通过Class::getResource方法获取其自己资源之一的URL。这些方法不会在其他命名模块中找到资源。

  • ClassLoader::getResource*方法找不到任何资源 命名模块。

  • ClassClassLoader中的所有现有资源查找方法与今天针对类路径上的资源的工作方式相同。

  • 新的Module::getResourceAsStream方法可以 用于读取任何命名模块的资源,没有限制。

这些选择可以在Jigsaw的resource encapsulationreadable artifact要求之间取得平衡。

答案 1 :(得分:0)

由于转向模块化架构,不再支持查找类路径的旧方法:

  

应用程序类加载器不再是实例   URLClassLoader,而不是内部类。这是默认值   用于既不是Java SE也不是JDK的模块中的类的加载器   模块。

https://docs.oracle.com/javase/9/migrate/toc.htm

您可以尝试直接解析classpath属性,或尝试使用ModuleFinder和朋友对模块执行某些操作。

答案 2 :(得分:0)

我找到的最佳答案是为getResources提供一个参数,当然这意味着你知道资源所在路径的前缀

  ArrayList<URL> resources = new ArrayList<URL>();
  ClassLoader urlLoader = ClassLoader.getSystemClassLoader();
  Enumeration<URL> eU = urlLoader.getResources("com");
  while (eU.hasMoreElements()) {
     URL u = eU.nextElement();
     JarFile jarFile = new JarFile(u.getFile().replace("file:/", "").replaceAll("!.*$", ""));
     Enumeration<JarEntry> e = jarFile.entries();
     while (e.hasMoreElements()) {
        JarEntry jarEntry = e.nextElement();
        resources.add(urlLoader.getResource(jarEntry.getName()));
     }
  }