在Java 9中运行时扫描类路径/模块路径

时间:2017-01-30 09:36:19

标签: java classpath java-9 jigsaw java-module

我似乎无法找到关于是否仍然可以在运行时扫描所有可用类(用于接口,注释等)的任何信息,就像Spring,Reflections和许多其他框架和库当前所做的那样,面对面Jigsaw的相关变化与类的加载方式有关。

修改 : 这个问题是关于扫描寻找类的真实物理文件路径。 The other question是关于动态加载类和资源。它有关但非常不重复

更新 :Jetty项目为此标准化API提供了JEP proposal。如果你有办法帮助实现这个目标,请做。否则,等等和希望。

更新2 :找到了this相关的发声帖子。引用后代的代码片段:

  

如果您真的只是想了解模块的内容   启动层(启动时解析的模块)然后你就可以了   像这样的东西:

  ModuleLayer.boot().configuration().modules().stream()
         .map(ResolvedModule::reference)
         .forEach(mref -> {
             System.out.println(mref.descriptor().name());
             try (ModuleReader reader = mref.open()) {
                 reader.list().forEach(System.out::println);
            } catch (IOException ioe) {
                 throw new UncheckedIOException(ioe);
             }
         });

2 个答案:

答案 0 :(得分:18)

以下代码在Java 9+(Jigsaw)中实现了模块路径扫描。它会在callstack上找到所有类,然后为每个类引用调用classRef.getModule().getLayer().getConfiguration().modules(),它会返回一个List<ResolvedModule>,而不仅仅是List<Module>。 (ResolvedModule使您可以访问模块资源,而Module则不会。)给定每个模块的ResolvedModule引用,您可以调用.reference()方法来获取{ {1}}用于模块。 ModuleReference为您提供ModuleReference#open(),您可以使用ModuleReader列出模块中的资源,也可以使用ModuleReader#list()Optional<InputStream> ModuleReader#open(resourcePath)打开资源。然后,在完成模块后关闭Optional<ByteBuffer> ModuleReader#read(resourcePath)。这在我见过的任何地方都没有记录。要弄清楚这一切是非常困难的。但这是代码,希望其他人能从中受益。

请注意,即使在JDK9 +中,您仍然可以使用传统的类路径元素以及模块路径元素,因此对于完整的模块路径+类路径扫描,您应该使用适当的类路径扫描解决方案,例如ClassGraph,它使用以下机制支持模块扫描(免责声明,我是作者)。

ModuleReader

答案 1 :(得分:2)

这里的实际问题是找到类路径上所有jar和文件夹的路径。一旦你拥有它们,你就可以扫描。

我所做的是以下内容:

  • 获取当前类的当前模块描述符
  • 获取所有requires个模块
  • 为每个此类模块打开资源MANIFEST.MF
  • 从资源网址
  • 中删除MANIFEST.MF路径
  • 剩下的是模块的类路径,即它的jar或文件夹。

我对当前模块执行相同的操作,以获取当前代码的类路径。

这样我收集当前工作模块的类路径及其所有必需的模块(1步之外)。这对我有用 - 我的Java8扫描仪仍然可以完成这项工作。此方法不需要任何其他VM标志等。

我可以扩展这种方法以轻松获取所有所需模块(不仅仅是第一级),但就目前而言,我并不需要。

Code