如何在Java 9中枚举非系统模块

时间:2017-12-22 05:33:31

标签: java classpath java-9 java-module

更新:我在这里回答了我自己的问题:

Scanning classpath/modulepath in runtime in Java 9

-

[旧问题 - 已废弃:]

在Java 9模块系统中,您可以使用

查找系统模块
Set<ModuleReference> ms = ModuleFinder.ofSystem().findAll();

然后可以使用这些ModuleReference对象列出每个模块的内容:

for (ModuleReference m : ms) {
    System.out.println(m.descriptor().name());
    System.out.println(" " + m.descriptor().toNameAndVersion());
    System.out.println(" " + m.descriptor().packages());
    System.out.println(" " + m.descriptor().exports());
    Optional<URI> location = m.location();
    if (location.isPresent()) {
        System.out.println(" " + location.get()); // e.g. "jrt:/java.base"
    }
    m.open().list().forEach(s -> System.out.println("  " + s));
}

要获取当前类的模块,可以使用

Module m = getClass().getModule();

但我似乎无法从此ModuleReference获得Module(因此我无法列出模块的内容,而不是软件包)和非{ -Module未列出系统ModuleFinder

两个问题:

  1. 如何枚举非系统模块中的资源?
  2. 如何在JRE 9中读取非模块类路径?我应该依赖java.class.path系统属性吗? (类型AppClassLoader#ucp的{​​{1}}字段不可见,并且在JRE 9中被锁定,因此您无法通过内省获得它。)

1 个答案:

答案 0 :(得分:4)

这个怎么样:

Set<String> systemModuleNames = ModuleFinder
        .ofSystem()
        .findAll()
        .stream()
        .map(moduleRef -> moduleRef.descriptor().name())
        .collect(Collectors.toSet());

List<Module> nonSystemModules = ModuleLayer
        .boot()
        .modules()
        .stream()
        .filter(m -> !systemModuleNames.contains(m.getName()))
        .collect(Collectors.toList());

System.out.println(nonSystemModules);

现在,当您拥有nonSystemModules时,您可以使用此列表执行任何操作(例如,获取每个模块中的资源)。