JavaFX-ProviderNotFoundException : Provider not found

标签 java javafx nio

我正在使用 jlink 构建我的 JavaFX 应用程序以及所需的 JVM (openjdk-18.0.2.1) 组件。 构建脚本与默认使用 IDEA 创建的脚本几乎没有什么区别。

import org.gradle.internal.os.OperatingSystem

plugins {
    id 'java'
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.13'
    id 'org.beryx.jlink' version '2.25.0'
}

group 'com.prototype'
version '1.0'

repositories {
    mavenCentral()
}

ext {
    junitVersion = '5.9.0'
}

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(18))
    }
    //withSourcesJar()
}

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

application {
    mainModule = 'com.prototype.catassistant'
    mainClass = 'com.prototype.catassistant.CatAssistantApplication'
}

javafx {
    version = '18.0.1'
    modules = ['javafx.controls', 'javafx.fxml', 'javafx.web']
}

dependencies {

    // https://mvnrepository.com/artifact/org.jetbrains/annotations
    implementation 'org.jetbrains:annotations:23.0.0'

    implementation('org.controlsfx:controlsfx:11.1.1')

    // https://www.benf.org/other/cfr/api/index.html
    // https://mvnrepository.com/artifact/org.benf/cfr
    implementation 'org.benf:cfr:0.152'

    // https://mvnrepository.com/artifact/com.google.code.gson/gson
    implementation 'com.google.code.gson:gson:2.9.1'

    testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
}

test {
    useJUnitPlatform()
}

jlink {
    imageZip = project.file("${buildDir}/distributions/app-${javafx.platform.classifier}.zip")
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    jpackage {
        def currentOs = OperatingSystem.current()
        def imgType = currentOs.windows ? 'ico' : currentOs.macOsX ? 'icns' : 'png'
        icon = "src/main/resources/java.$imgType"
        if (currentOs.windows) {
            installerOptions += ['--win-per-user-install', '--win-dir-chooser', '--win-menu', '--win-shortcut', '--vendor', 'Prototype']
            imageOptions += ['--win-console',/* '--icon', 'src/main/resources/icon.ico'*/]
        }
    }
    launcher {
        name = 'CatAssistant'
    }
}

jlinkZip {
    group = 'distribution'
}

构建镜像后,我成功运行它并且它可以工作,但是当涉及到使用 jar 文件时,我收到一个难以理解的错误:java.nio.file.ProviderNotFoundException:未找到提供程序 IDEA 一切正常。我也很困惑,在构建之后,“(未知来源)”被写入整个堆栈跟踪而不是代码行,如果存在这种可能性,我想修复它。

Caused by: java.nio.file.ProviderNotFoundException: Provider not found
        at java.base/java.nio.file.FileSystems.newFileSystem(Unknown Source)
        at java.base/java.nio.file.FileSystems.newFileSystem(Unknown Source)
        at <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="12717d7f3c62607d667d666b62773c7173667361617b6166737c6652233c22" rel="noreferrer noopener nofollow">[email protected]</a>/com.prototype.catassistant.helper.FileHelper.readJarFile(Unknown Source)

FileHelper#readJarFile

    // https://stackoverflow.com/a/37413531/10663941
    public static void readJarFile(JarFile jar) {
        try (FileSystem system = FileSystems.newFileSystem(jar.getPath())) { // <- exception
            for (Path directory : system.getRootDirectories()) {
                try (Stream<Path> stream = Files.walk(directory)) {
                    stream.filter(Predicate.not(Files::isDirectory))
                            .forEach(path -> jar.addEntry(path, read(system.getPath(path.toString()))));
                }
            }
        } catch (IOException ex) {
            AlertUtil.showExceptionDialog(ex);
            throw new RuntimeException(ex);
        }
    }

我需要帮助来解决这个问题

最佳答案

ProviderNotFoundException

java.nio.file.ProviderNotFoundException 错误很可能是由 jdk.zipfs 引起的模块未包含在 jlink/jpackage1 创建的运行时镜像中。该模块是 java.nio.file.FileSystemProvider 的“提供者模块” SPI。因此,我怀疑应用程序中直接或间接一部分的其他模块都不需要 jdk.zipfs 模块。通常,模块不需要 requires 提供者模块,因为这违背了 Java 平台模块系统的 uses/provides 机制的目的(请参阅下面第二个解决方案中的链接以获取说明)。

可以通过三种方法解决此问题:

  1. 调用jlink时使用--bind-services。这将导致 jlink 查看所有必需的模块,以查看其中是否有任何使用 SPI。如果是,那么它将查找提供 SPI 实现的所有可用模块并包含它们。不幸的是,这将导致您的自定义运行时镜像中包含许多您不一定需要的其他模块。

  2. 修改模块信息描述符以添加 requires jdk.zipfs 指令。然而,正如 the documentation 中所述,拥有“应用程序模块”需要“提供者模块”是 not recommended .

  3. 调用 jlink 时包含 --add-modules jdk.zipfs 参数。这将强制jlink包含jdk.zipfs模块,而不会产生前两个解决方案的不幸的副作用。就我个人而言,我建议在您的情况下使用此解决方案。

来源未知

堆栈跟踪中的“未知来源”位是由 --strip-debug 参数引起的,不出所料,该参数会从字节码中删除调试信息。其中包括源文件名和行号。使用 --strip-debug 可以减少编译代码的大小,这有利于应用程序的部署版本。


1. 您已 confirmed this .

关于JavaFX-ProviderNotFoundException : Provider not found,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73587338/

相关文章:

Java NIO : how to protect global data effectively?

JAVA NIO ByteBuffer 分配以适应最大的数据集?

java - 使用 Java 检查数据库是否正在运行

java - 速度找不到方法

java - SocketChannel read() 行为 - 短读取

java - 为什么我收到 java.sql 可能无法访问客户端由于缺少 'requires transitive'

java - 如何从非 JavaFX 线程调用 JavaFX Controller 并等待 GUI 更改完成(完成播放视频)?

java - 尝试让java程序连接到Mac上的本地Mysql数据库

java - 在JFrame中打开excel文件时出现异常

java - 如何在 JavaFX 中创建通用确认对话框