也许是 Java 环境的一个 BUG

openSUSE 在安装 Java 模块比如 OpenJFX 之后,不会把路径加入 Java 本身的运行环境中。必须要用--module-path选项强制制定模块的目录,并用--add-modules选项指明要加载的模块。

例如,安装好相应软件包后,在 Arch 上只要一句:

java -jar abc.jar

到 openSUSE 上就变成:

java --module-path /usr/share/java/openjfx/ --add-modules javafx.base,javafx.controls,javafx.fxml,javafx.graphics,javafx.media,javafx.swing,javafx.web -jar abc.jar

问题在于,有些时候用户并不知道程序要加载什么模块,然后就彻底无法运行程序了。请问这是一个打包上的错误,还是 work as intended

Arch Linux 有个这个东西:

大概就是设置默认 java 环境

openSUSE 的 openjdk 只有 headless 版本有 update-alternative 操作设置默认 java…

你试试装 headless 版本看看是不是这个原因

所以你们打包 Java 模块的时候真的不配置 Java 环境?:rofl:怎么看都很奇怪啊,为啥会有这么奇怪的打包?

况且 Arch 的这个脚本好像不是解决这个问题的,他不是切换 Java 环境用的吗? 修改/usr/lib/jvm/default的时候用的,但 openSUSE 会把一些 Java 模块安装在 /usr/share/java/下的独立文件夹,比如/usr/share/java/openjfx/

默认安装的就是 headless 版本。

@BearChild

openSUSE 装到独立文件夹下对应 Arch Linux 是怎么做的?这问题不就定位出来了嘛…

openSUSE 用 java 的这么多年我就知道一个 @java2learner。混英文 mailinglist 的时候都没见过…你要这么想粗放就正常了…用的人少能包上就不错了 :joy:

装的位置不一样,同为 Java11 版,Arch 就装在/usr/lib/jvm/java-11-openjfx/下面,但问题不在装在哪儿,问题在于怎样让 Java 自动去合适的地方寻找安装的模块(悲伤),我去英文论坛问一问好了。

你怎么会有这么奇怪的需求。

如果开发者打算弄一个” 一次编译,到处运行 “的 jar,开发者会把所有的依赖都放进 jar 里面,然后用户才可以在任何存在 JVM 的环境下来直接启动。也从来没见过那个独立运行的 jar 不提供所有依赖。

对于发行版来说,用户执行的 jar,都会用一个 shell 脚本包裹一下,再加上一些调整 jvm 的参数。不可能存在安装一个 .jar 让用户通过命令行执行,再多的参数也没有问题,反正正常用户又不管。如果不懂的用户非要自己手动启动 jar,就是会很麻烦。“普通 “用户甚至不需要知道 java 这个命令。

系统提供的 modules 版本又不一定适合一些程序。如果开发者要求桌面用户通过要求系统中存在某个 module 来单独运行自己的 JAVA 程序,那么他一定是想要折磨用户。

在 Java9 以前,没有 module 的时候,那个 jar 运行的时候还要指定一波 class-path 去依赖用户系统带的那个 ???

剩下的用户就是开发者,那个不是从 maven 里面直接拉。对于 java sdk 以外的包,去引用系统带的那个,就是在自己找不愉快。

再剩下的跑在服务器上的,想用 module 来组织组件,你改了全局的默认的 module,我还可以说,你在污染环境。

–add-modules 就像 C 的 #include,正常用户为什么需要知道自己运行的程序使用了什么模块,然后手动 include ?

Java 又不是 C。在 Java 的世界里面根本不存在你说的 ” 有些用户 “。

我甚至找不到那个 Java 应用程序分发一个不带依赖的 jar,让用户自己下载依赖,然后指定 class-path/module-path。

javafx 早就在标准的 java 里面被排除掉了,算作是独立的包 openjfk。本来就不是 jvm 的一部分,还要丢到 jvm/ 目录里面才奇怪。

哥,我不知道你为何会有这种观点。

首先,所有的依赖都放进 jar 里面就是奇怪的做法,至少在我接触的 Java 桌面应用里,没见过这种。顶天了做一个只用 JavaSDK 内的模块的小东西,然后自己下载依赖——依然是一堆 Jar。

其次,JavaFX 本身不能做到 “一次编译,到处运行”,因为其带有部分二进制动态链接库。

再三,“还要丢到 jvm 目录里面才奇怪” 这种说法不要对着我说,请直接告诉 Arch Linux 的打包者,我不在意他放在哪儿,放到旅行者一号上也没关系,我只想要他正常启动。而且甲骨文 JRE 是自带 JavaFX 的,所以在 Windows、Mac 还有 Arch 下的用户不会碰到这个问题。还真就是 work as intended 呗。

最后,能上 Linux 桌面的都算是自找麻烦,能有几个算 “普通用户”?虽然对于 Java,我就是个普通用户,连 Class、Jar 与 Module 的关系都不知道,但我知道 openSUSE 的 Java 与 Windows、MacOS、Arch 长得不同,别样眉清目秀。得,我自找折磨,我不求您帮我,但也请别给我添堵,我提前谢谢您了。也谢谢苏姐。

javafx 在的甲骨文的 java 里面,removed

讲真,JavaFX 在哪儿我不在乎,至少我在 Java 的网站 上下载 Java8 的时候,他在,然后能用。但 openSUSE 的 OpenJDK8 里就没有,而且,软件源里 Java8 版 OpenJFX 缺失了一些组件,所以我只能用 Java11 版的。然后在 Arch 上,虽然不在 OpenJDK 里,但直接安装就能用,与甲骨文 JRE 表现一致。

如果你想说:“没错,Work as intended。” 那就请说。

@BearChild 应该不是 work as intended。我感觉还是 openjfx 打包的问题。但是我真的对 java 一窍不通。java 是怎么定义 module-path 的你了解吗?就是类似配置文件之类的。我只了解打包。我看了 Arch Linux 那边的 openjfx 好像也没特殊做什么,我感觉是 openjdk 的问题,但是 Arch Linux 那边对 openjdk 更没有做啥了(那个 java-common 除外)基本就是 vanilla 发布…

我连一行 Java 代码都没碰过,更不用说了解。:rofl: 我只是单纯的想跑那个 Jar,那个在 Windows、Mac 还有 Arch 下都能跑的 Jar 而已(悲伤)。等我去英文论坛上问问再说吧,反正我也就只碰这一个 Jar,解决方案脏一点也不是不能接受,我只是觉得本来不该这样奇怪的而已。

理论上确实不应该这么奇怪啊…那个 jar 能发出来吗,我下载了等开电脑的时候研究一下…Java 不是 C,我都不知道 strace 对它有没有用…

@marguerite 虽然没什么必要,我觉得就是单纯的配置问题,也不麻烦您开电脑了,我直接把 strace 结果贴一部分在下面好了:

execve("/usr/bin/java", ["java", "-jar", "HMCL.jar"], 0x7ffdd0513c40 /* 95 vars */) = 0
brk(NULL)                               = 0x563a1f250000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffc9b232ee0) = -1 EINVAL (无效的参数)
readlink("/proc/self/exe", "/usr/lib64/jvm/java-11-openjdk-1"..., 4096) = 42
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/tls/haswell/x86_64/libjli.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
stat("/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/tls/haswell/x86_64", 0x7ffc9b232090) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/tls/haswell/libjli.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
stat("/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/tls/haswell", 0x7ffc9b232090) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/tls/x86_64/libjli.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
stat("/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/tls/x86_64", 0x7ffc9b232090) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/tls/libjli.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
stat("/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/tls", 0x7ffc9b232090) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/haswell/x86_64/libjli.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
stat("/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/haswell/x86_64", 0x7ffc9b232090) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/haswell/libjli.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
stat("/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/haswell", 0x7ffc9b232090) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/x86_64/libjli.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
stat("/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/x86_64", 0x7ffc9b232090) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/lib64/jvm/java-11-openjdk-11/bin/../lib/jli/libjli.so", O_RDONLY|O_CLOEXEC) = 3

后面还有一堆这种 “没有那个文件或目录” 的错误。

这是 Jar 的链接:(也是开源软件)
http://ci.huangyuhui.net/job/HMCL/172/artifact/HMCL/build/libs/HMCL-3.3.172.jar

java moulde 是 java9 开始的,之前都是用 class-path

java 的默认的 module-path 是直接扫描 jvm 下面的目录,其他的都要通过 java -module-path -add-module 来指定,并没有一个环境变量来控制,(只能通过命令行指定,应该是以前指定 CLASSPATH 有些痛苦的经历)。

对 Oracle java 来说
openjfx 是 java8 的一部分
后来从 java11 中移除了。

结果就是各大发行版都有两个版本的 openjfx,openSUSE 里面有 openjfx8 和 openjfx 分别给 8 和 11。

在 openSUSE 上
openjfx8 安装在 /usr/lib/jvm 作为 jvm 的一部分,以老式的 class-path 形式存在
openjfx 安装再 /usr/share 作为一个外部的库,以 module 的形式存在

但是 javafx 作为很少有人用的东西(被移除的原因之一),openSUSE 并没有再安装 openjdk8 以后默认安装 openjfx8。应该也有其它发行版做类似的事情。

对给 java 11 的 openjfx
Debian 和 openSUSE 都把 openjfx 放在 /usr/shar
Fedora 和 Arch 把 openjfx 放在 usr/lib/jvm。

但是 Fedora 是把以前 java8 的 spec 文件复制粘贴,所以依旧再 /usr/lib/jvm 里面。

而且,老一点的程序默认 javafx 存在,所以一些发行版会继续再 11 和以后的版本像以前 java8 一样默认安装。

===

但是我认为,对于上游的开发者,如果要自己以 jar 的形式分发 Java 程序,应该会制作 win/linux/mac 三个版本的 jar,里面的资源文件里面含对应的二进制部分。

对于对应平台的打包者,则会加一个启动脚本来指定系统的 openjfx。就算是 windows 版本,也会套一层启动程序的壳然后合并成 .exe。

对于开发者自身,则应该直接从 Maven 里面拉去正确的版本。

所以自己指定 module-path 的应用场景并不存在,

===
他拿到的 jar 文件应该是比较古老的那种,或者明确要求 java8,在 openSUSE 上安装 openjfx8 应该就可以了。但是如果不想麻烦,可以一考虑下 oracle java8.

2赞

就连那个项目自己也是这样认为的。

openSUSE 的打包方式没有问题,11 版紧贴上游直接移除 openjfx,

8 版本由于 服务器用户 >>>> 桌面,而不默认安装,并没有什么问题。而且 AdoptOpenjdk8/Amazon corretto8/Azure Zulu 8 同样也不包含 openjfx。


手动安装openjfx8也没用,缺东西,软件包的描述是 “The media and Web module have been removed due to missing dependencies.” 实际上也确实用不了,就算安装在/usr/lib64/jvm/openjfx8,照样提示缺少 OpenJFX,这就是奇葩的地方。

是,我就已经安装了 Oracle Java8,我只是来问问这是不是个 BUG 而已。那个 Jar 开源,openSUSE 也开源,OpenJDK 与 OpenJFX 还是开源,但到头来还得回到 Oracle Java8,这大概就是开源的 Java
精神吧。 :coffee:(悲伤)

还真是 Working as intended。总之谢谢你。

在 OpenJDK 11 下引用 JavaFX 必须加上--module-path

java --module-path /usr/share/java/openjfx/ --add-modules javafx.base,javafx.controls,javafx.fxml,javafx.graphics,javafx.media,javafx.swing,javafx.web -jar abc.jar

或者直接使用 Oracle Java 8 环境。OpenJFX 8 因缺失依赖不完整。

具体原因如下:

学习了…有了你普及的这些知识以后看 Java:Packages 里的包就更方便了,我还是 Android 出来那年修 maven 失败后发誓再也不碰 Java 的…

1赞

本主题在最后一个回复创建后60分钟后自动锁定。不再允许添加新回复。