假设我们有模块 A 动态加载模块 B (使用类 ModuleFinderModuleLayer 等) . 最后一个需要标准模块 java.sql ,它未加载到模块 A 的引导层中 . 如何使用java代码从JDK(或JRE)加载所需的 java.sql

EDIT

这个示例maven项目演示了我的问题:

项目结构:

│   pom.xml
│
├───loader
│   │   pom.xml
│   │
│   └───src
│       ├───main
│       │   ├───java
│       │   │   │   module-info.java
│       │   │   │
│       │   │   └───app
│       │   │       └───module
│       │   │           └───loader
│       │   │                   AppLoader.java
│       │   │                   AppModule.java
│       │   │
│       │   └───resources
│       └───test
│           └───java
└───sql-module
    │   pom.xml
    │
    └───src
        ├───main
        │   ├───java
        │   │   │   module-info.java
        │   │   │
        │   │   └───app
        │   │       └───module
        │   │           └───sql
        │   │                   SQLAppModule.java
        │   │
        │   └───resources
        └───test
            └───java

pom.xml中:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>sample-app</artifactId>
        <groupId>sample-app</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>loader</artifactId>
</project>

装载机/ pom.xml中:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>sample-app</artifactId>
        <groupId>sample-app</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>loader</artifactId>
</project>

装载机/ src目录/主/ JAVA / module-info.java:

module app.module.loader {
    exports app.module.loader;
    uses AppModule;
}

装载器/ SRC /主/ JAVA /应用程序/模块/装载器/ AppLoader.java:

public class AppLoader {
    public static void main(String[] args) {
        var path = Paths.get("sql-module", "target", "classes");
        var moduleFinder = ModuleFinder.of(path);
        var boot = ModuleLayer.boot();
        var config = boot.configuration().resolveAndBind(moduleFinder, ModuleFinder.of(), Collections.emptyList());
        var newLayer = boot.defineModulesWithOneLoader(config, Thread.currentThread().getContextClassLoader());
        var testModule = ServiceLoader.load(newLayer, AppModule.class)
                .findFirst()
                .orElseThrow(() -> new RuntimeException("Module not found!"));
        System.out.println("Module name: " + testModule.name());
        System.out.println("Module version: " + testModule.version());
    }
}

装载器/ SRC /主/ JAVA /应用程序/模块/装载器/ AppModule.java:

public interface AppModule {
    String name();
    String version();
}

SQL模块/ pom.xml中:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>sample-app</artifactId>
        <groupId>sample-app</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>sql-module</artifactId>
    <dependencies>
        <dependency>
            <groupId>sample-app</groupId>
            <artifactId>loader</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

SQL模块/ SRC /主/爪哇/ module-info.java:

module app.module.sql {
    requires app.module.loader;
    requires java.sql;

    provides AppModule with SQLAppModule;
}

SQL模块/ SRC /主/ JAVA /应用程序/模块/ SQL / SQLAppModule.java:

public class SQLAppModule implements AppModule {
    public SQLAppModule() {
        List<Driver> drivers = DriverManager.drivers().collect(Collectors.toList());
        System.out.println("Drivers on class path: " + drivers.size());
        drivers.forEach(d -> {
            System.out.println("Driver: " + d.toString());
            System.out.println("Version: " + d.getMajorVersion() + "." + d.getMinorVersion());
        });
    }

    @Override
    public String name() {
        return "SQL Module";
    }

    @Override
    public String version() {
        return "1.0-SNAPSHOT";
    }
}

当您尝试在 AppLauncher 中使用main启动应用程序时,您将收到错误(我现在使用jdk-10.0.1):

Exception in thread "main" java.lang.module.FindException: Module java.sql not found, required by app.module.sql
    at java.base/java.lang.module.Resolver.findFail(Resolver.java:877)
    at java.base/java.lang.module.Resolver.resolve(Resolver.java:191)
    at java.base/java.lang.module.Resolver.bind(Resolver.java:297)
    at java.base/java.lang.module.Configuration.resolveAndBind(Configuration.java:482)
    at java.base/java.lang.module.Configuration.resolveAndBind(Configuration.java:288)
    at app.module.loader/app.module.loader.AppLoader.main(AppLoader.java:14)

怎么样hacks:我认为它们必须在最后一个地方使用,所以我们试图找到或多或少的方法来实现它 .

This answer无法解决此问题,因为启动时的 layer.findModule(moduleName).orElse(null) 或任何其他图层将返回null .