Module java.base
Package java.lang.module

Interface ModuleFinder


public interface ModuleFinder
模块查找器。在解析服务绑定期间使用ModuleFinder来查找模块。

ModuleFinder只能找到给定名称的一个模块。例如,查找一系列目录中的模块的ModuleFinder将定位给定名称的第一个模块,并将忽略后续目录中出现的同名其他模块。

示例用法:

    Path dir1 = ..., dir2 = ..., dir3 = ...;
    ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
    Optional<ModuleReference> omref = finder.find("jdk.foo");
    omref.ifPresent(mref -> ... );

这里定义的findfindAll方法可能因多种原因而失败。这些原因包括I/O错误、检测到解析模块描述符(module-info.class)时的错误,或者在由ModuleFinder.of返回的ModuleFinder中,一个目录中找到两个或更多同名模块。当检测到错误时,这些方法将抛出一个带有适当FindExceptioncause的异常。在抛出FindException后,ModuleFinder的行为是未定义的。例如,在抛出异常后调用find可能会扫描导致异常的相同模块,也可能不会。建议在抛出异常后丢弃模块查找器。

ModuleFinder不要求是线程安全的。

自 JDK 版本:
9
  • Method Summary

    Modifier and Type
    Method
    Description
    static ModuleFinder
    compose(ModuleFinder... finders)
    返回由零个或多个模块查找器组成的模块查找器。
    find(String name)
    查找给定名称的模块的引用。
    返回此查找器可以定位的所有模块引用集。
    static ModuleFinder
    of(Path... entries)
    返回一个模块查找器,通过搜索一系列目录和/或打包模块来定位文件系统上的模块。
    static ModuleFinder
    返回一个定位系统模块的模块查找器。
  • Method Details

    • find

      查找给定名称的模块的引用。

      ModuleFinder提供其定位的模块的一致视图。如果多次调用find来定位相同模块(按名称),则每次都将返回相同的结果。如果定位了一个模块,则它保证是findAll方法返回的模块集合的成员。

      参数:
      name - 要查找的模块的名称
      返回:
      具有给定名称的模块引用,如果未找到则为空的Optional
      抛出:
      FindException - 如果查找模块时发生错误
      SecurityException - 如果被安全管理器拒绝
    • findAll

      Set<ModuleReference> findAll()
      返回此查找器可以定位的所有模块引用集。

      ModuleFinder提供其定位的模块的一致视图。如果多次调用findAll,则每次都将返回相同(相等)的结果。对于返回集合中的每个ModuleReference元素,如果调用find来查找该模块,则保证会定位到ModuleReference

      API 注意:
      对于需要扫描模块路径以查找提供特定服务的模块的方法(例如resolveAndBind),这一点非常重要。
      返回:
      此查找器定位的所有模块引用集
      抛出:
      FindException - 如果查找所有模块时发生错误
      SecurityException - 如果被安全管理器拒绝
    • ofSystem

      static ModuleFinder ofSystem()
      返回一个定位系统模块的模块查找器。系统模块是Java运行时映像中的模块。模块查找器将始终找到java.base

      如果设置了安全管理器,则将调用其checkPermission方法来检查调用者是否被授予访问系统模块的RuntimePermission("accessSystemModules")权限。

      返回:
      定位系统模块的ModuleFinder
      抛出:
      SecurityException - 如果被安全管理器拒绝
    • of

      static ModuleFinder of(Path... entries)
      返回一个模块查找器,通过搜索一系列目录和/或打包模块来定位文件系统上的模块。给定数组中的每个元素是以下之一:
      1. 模块目录的路径。

      2. 爆炸模块的顶级目录的路径。

      3. 打包模块的路径。

      模块查找器通过按照数组索引顺序搜索每个目录、爆炸模块或打包模块来定位模块。它找到具有给定名称的模块的第一个出现,并忽略后续出现在序列中的具有相同名称的其他模块。

      如果一个元素是模块目录的路径,那么目录中的每个条目都是打包模块或爆炸模块的顶级目录。如果一个目录包含多个具有相同名称的模块,则会报错。如果一个元素是目录的路径,并且该目录包含名为module-info.class的文件,则该目录将被视为爆炸模块而不是模块目录。

      此方法返回的模块查找器支持打包为JAR文件的模块。具有module-info.class在其顶级目录或在多版本 JAR文件中的版本化条目中的JAR文件是模块化JAR文件,因此定义了一个显式模块。没有module-info.class在其顶级目录中的JAR文件定义为自动模块,如下所示:

      • 如果JAR文件的主清单中具有属性"Automatic-Module-Name",则其值为模块名称。否则,模块名称将从JAR文件的名称派生。

      • 版本,以及当属性"Automatic-Module-Name"不存在时的模块名称,将根据JAR文件的文件名派生如下:

        • 去除".jar"后缀。

        • 如果名称匹配正则表达式"-(\\d+(\\.|$))",则模块名称将从第一个连字符之前的子序列派生。连字符之后的子序列被解析为Version并且如果无法解析为Version则被忽略。

        • 模块名称中的所有非字母数字字符([^A-Za-z0-9])将替换为点("."),所有重复的点将替换为一个点,并且所有前导和尾随点将被移除。

        • 例如,名为"foo-bar.jar"的JAR文件将派生模块名称"foo.bar",没有版本。名为"foo-bar-1.2.3-SNAPSHOT.jar"的JAR文件将派生模块名称"foo.bar"和版本"1.2.3-SNAPSHOT"。

      • 模块中的包集合是从JAR文件中不以".class"结尾的非目录条目派生的。候选包名称是使用直到最后一个正斜杠之前的字符从名称派生的。所有剩余的正斜杠将替换为点(".")。如果结果字符串是合法的包名称,则假定它是包名称。例如,如果JAR文件包含条目"p/q/Foo.class",则派生的包名称是"p.q"。

      • META-INF/services/开头的条目的内容被假定为服务配置文件(参见ServiceLoader)。如果文件的名称(跟在META-INF/services/后面)是合法的类名,则假定它是服务类型的完全限定类名。文件中的条目被假定为提供者类的完全限定类名。

      • 如果JAR文件的主清单中具有Main-Class属性,则其值是合法的类名,并且其包含在为模块派生的包集合中,则该值是模块的主类

      如果无法创建ModuleDescriptor(通过ModuleDescriptor.Builder API)用于自动模块,则会抛出FindException。当"Automatic-Module-Name"属性的值不是合法的模块名称,无法从JAR文件的文件名派生合法的模块名称,JAR文件包含JAR文件顶级目录中的.class,服务配置文件中的条目不是合法的类名或其包名不在为模块派生的包集合中时,可能会出现这种情况。

      除了JAR文件外,实现还可以支持打包在其他实现特定模块格式中的模块。如果传递给此方法的数组中的元素是模块目录的路径,则将忽略目录中未被识别为模块的条目。如果数组中的元素是未被识别的打包模块的路径,则在遇到该文件时将抛出FindException。不存在的文件路径始终会被忽略。

      与自动模块一样,打包或爆炸模块的内容可能需要进行扫描以确定模块中的包。是否忽略隐藏文件是实现特定的,因此未指定。如果在顶级目录中找到.class文件(除了 module-info.class),则假定它是未命名包中的类,因此会抛出FindException

      此方法创建的查找器是惰性的,不会急切地检查给定的文件路径是否为目录或打包模块。因此,只有在调用这些方法导致搜索目录或打包模块并遇到错误时,findfindAll方法才会失败。

      参数:
      entries - 可能为空的目录路径数组,包含模块目录或打包或爆炸模块的路径
      返回:
      定位文件系统上模块的ModuleFinder
    • compose

      static ModuleFinder compose(ModuleFinder... finders)
      返回一个由零个或多个模块查找器序列组成的模块查找器。结果模块查找器的find方法将通过调用每个模块查找器的find方法(按照数组索引顺序)来定位模块,直到找到模块或所有模块查找器都已搜索完毕。结果模块查找器的findAll方法将返回一个包含由第一个模块查找器定位的所有模块的集合。该集合将包括由第二个或后续模块查找器定位的所有模块,这些模块不是由前面的模块查找器在序列中定位的。

      在定位模块时,由底层模块查找器的findfindAll方法抛出的任何异常或错误将传播到结果模块查找器的findfindAll方法的调用者。

      参数:
      finders - 模块查找器数组
      返回:
      组成模块查找器序列的ModuleFinder