我一直在尝试通过Hello World和Hello JFX World程序的实验将程序迁移到jlink。在执行程序时,我遵循的示例似乎指定了--add-modules。我不明白为什么该程序需要运行时提供的jlink时所需的信息。

我现在已经成功构建了一个简单的jlink Hello World程序,该程序无需在命令行上使用--add-modules即可运行。技巧是更改jlink模块路径上指定的模块顺序。我不知道为什么这样。

JDK-9,JDK-10或JDK-11文档在哪里指定或描述了该jlink行为?应该如何去构建模块路径?

另外:这种有序的链接在30年前很常见,当时我曾经在DEC PDP-11小型计算机上链接Fortran IV和Macro-11程序。当我要放弃时,我想尝试摆弄jlink的顺序

module-info.java:

module TestFXord {
    requires javafx.controls;
    exports testfxord to javafx.graphics;
}


TestFXord.java:

package testfxord;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class TestFXord extends Application {

    @Override
    public void start(Stage primaryStage) {

        Button btn = new Button();
        btn.setText("Say 'Hello World'");
        btn.setOnAction((ActionEvent event) -> {
            System.out.println("Hello World!");
        });

        StackPane root = new StackPane();
        root.getChildren().add(btn);
        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}


不产生可运行映像的jlink命令

#! /bin/sh
<jdk-11-path>/bin/jlink --module-path <jdk-11-path>/jmods:<javafx-sdk-11-path>/lib/javafx.base.jar:<javafx-sdk-11-path>/lib/javafx.controls.jar:<javafx-sdk-11-path>/lib/javafx.graphics.jar:<javafx-jmods-11-path>:<path-to-projects>/TestFXord/dist/TestFXord.jar --add-modules TestFXord --strip-debug --launcher TestFXord=TestFXord/testfxord.TestFXord --output dist/jlink/TestFXord


确实会生成可运行映像的jlink命令。请注意,现在立即显示在它所依赖的位置之后。

#! /bin/sh
    <jdk-11-path>/bin/jlink --module-path <jdk-11-path>/jmods:<javafx-jmods-11-path>:<javafx-sdk-11-path>/lib/javafx.base.jar:<javafx-sdk-11-path>/lib/javafx.controls.jar:<javafx-sdk-11-path>/lib/javafx.graphics.jar:<path-to-projects>/TestFXord/dist/TestFXord.jar --add-modules TestFXord --strip-debug --launcher TestFXord=TestFXord/testfxord.TestFXord --output dist/jlink/TestFXord


我估计jlink会逐步建立符号表,将符号映射到地址,从左至右在模块路径中向下工作,并解析(为其找到地址)具有地址的符号,并添加新的符号条目,发现它可以是用于解决后续模块中的呼叫。如果模块路径顺序正确,则在此过程中将解析每个符号。如果模块路径的顺序不正确,将存在尚未解析的符号。在运行映像时,用户将必须添加模块来解决剩余的符号。

换句话说,我不认为jlink会回到列表中来解析刚刚发现的早期模块中的符号。考虑一下,我怀疑这样做的原因是,每次添加新模块时都要返回搜索未解析的符号,这对于大型应用程序将需要更长的链接过程。那个听起来是对的吗?

最佳答案

作为@AlanBateman said in his comment


  指定给--module-path的模块路径是目录或模块的路径。因此,如果您指定多个具有相同模块版本的位置,顺序就很重要。


在两个示例中,您都在--module-path中包含JavaFX JMOD文件和JavaFX JAR文件。区别在于您添加它们的顺序。


工作示例:首先是JMOD文件。


jlink将使用JMOD文件中包含的模块

非工作示例:JMOD文件位于最后。


jlink将使用JAR文件中包含的模块



JavaFX SDK附带的JAR文件不包含任何必需的本机代码。如果链接到JAR文件,则生成的图像将无法执行。

但是,JMOD文件确实包含必要的本机代码。实际上,将本机代码与Java代码绑定在一起是实现JMOD格式的主要原因之一。从JEP 261


  新的JMOD格式超出了JAR文件的范围,包括了本机代码,配置文件和其他类型的数据,这些数据根本无法自然地适应JAR文件。 JMOD文件用于打包JDK本身的模块;如果需要,开发人员也可以使用它们来打包自己的模块。
  
  JMOD文件可以在编译时和链接时使用,但不能在运行时使用。为了在运行时支持它们,通常需要准备好即时提取和链接本机代码库。尽管这可能非常棘手,但在大多数平台上都是可行的,并且我们还没有看到许多需要此功能的用例,因此,为简单起见,我们选择限制此发行版中JMOD文件的实用性。


使用jlink时,应在可用的位置链接到JMOD文件。如果库不提供JMOD文件,则链接JAR文件。

综上所述,您应该将JavaFX JAR文件从--module-path完全删除-它们是不必要的,并且会引起混乱。

关于java - jlink --module-path是否为有序路径?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53240219/

10-11 20:19