Java

来自 ArchWiki

来自 Wikipedia 文章

Java 是一种编程语言,最初由 Sun Microsystems 开发,并于 1995 年作为 Sun Microsystems Java 平台的核心组件发布。 该语言的大部分语法都源自 C 和 C++,但具有更简单的对象模型和更少的底层工具。 Java 应用程序通常被编译为可以在任何 Java 虚拟机(JVM)上运行的字节码,而无需考虑计算机架构。

Arch Linux 官方支持开源 OpenJDK 版本 8、11、17 和 21(长期支持 (LTS) 版本)以及 23(最新发布版本)。 所有这些 JVM 都可以无冲突地安装,并使用辅助脚本 archlinux-java(与 java-runtime-common 软件包一起安装)进行切换。 Arch 用户仓库 中提供了其他几种 Java 环境,但未获得官方支持。

安装

注意
  • Arch Linux 仅官方支持 OpenJDK 实现。
  • 安装后,Java 环境需要被 shell$PATH 变量)识别。 这可以通过从命令行 sourcing /etc/profile,重新登录 桌面环境,或重新启动来完成。

两个通用软件包分别作为依赖项拉取,分别名为 java-runtime-common(包含 Java 运行时环境 的通用文件)和 java-environment-common(包含 Java 开发工具包 的通用文件)。

提供的 /etc/profile.d/jre.sh/etc/profile.d/jre.csh 文件指向链接位置 /usr/lib/jvm/default/bin,由 archlinux-java 辅助脚本设置。

提示: /usr/lib/jvm/default/usr/lib/jvm/default-runtime 符号链接应始终使用 archlinux-java 编辑,该脚本用于显示和指向正在工作的默认 Java 运行时环境。

Java 安装的大多数可执行文件由 /usr/bin/ 中的直接链接提供,而其他文件在 $PATH 中可用。

OpenJDK

OpenJDKJava 平台标准版 (Java SE) 的开源实现,被指定为官方参考实现。 有几个 OpenJDK 构建发行商,例如 Adoptium(以前称为 AdoptOpenJDK)和 Amazon Corretto。 Arch Linux OpenJDK 软件包是从 上游 OpenJDK 源代码 构建的。

无头 JRE
最小 Java 运行时环境 - 执行非 GUI Java 程序所必需。
完整 JRE
完整 Java 运行时环境 - 执行 GUI Java 程序所必需。
JDK
Java 开发工具包 - Java 开发所必需。

JDK、完整 JRE 和无头 JRE 相互冲突,因为较小的软件包是子集

  • JDK 冲突并提供完整 JRE,
  • 完整 JRE 冲突并提供无头 JRE。
版本 无头 JRE 完整 JRE JDK 文档 来源
OpenJDK 23 jre-openjdk-headless jre-openjdk jdk-openjdk openjdk-doc openjdk-src
OpenJDK 21 jre21-openjdk-headless jre21-openjdk jdk21-openjdk openjdk21-doc openjdk21-src
OpenJDK 17 jre17-openjdk-headless jre17-openjdk jdk17-openjdk openjdk17-doc openjdk17-src
OpenJDK 11 jre11-openjdk-headless jre11-openjdk jdk11-openjdk openjdk11-doc openjdk11-src
OpenJDK 8 jre8-openjdk-headless jre8-openjdk jdk8-openjdk openjdk8-doc openjdk8-src

IcedTea-Web — Java Web Start 和已弃用的 Java 浏览器插件。

https://icedtea.classpath.org/download/icedtea-web-docs/1.8/html/en/icedtea-web.html || icedtea-web

OpenJDK EA — 来自 Oracle 的开发版本的 OpenJDK 早期访问构建。

https://jdk.java.net || java-openjdk-ea-binAUR

OpenJDK GA — 来自 Oracle 的 OpenJDK 通用可用性版本构建。

https://jdk.java.net || java-openjdk-binAUR

OpenJDK Wakefield — 在 JDK 中对 Wayland 显示服务器的支持实现。

https://openjdk.org/projects/wakefield/ || jdk-openjdk-wakefieldAUR


OpenJFX

OpenJFXJavaFX 的开源实现。 如果您正在使用 Oracle JDK,则不需要安装此软件包。 此软件包仅与 Java(OpenJDK 项目)及其衍生产品的开源实现的用户有关。

版本 运行时环境和开发工具包 文档 来源
OpenJFX 22 java-openjfxAUR java-openjfx-docAUR java-openjfx-srcAUR
OpenJFX 21 java21-openjfxAUR java21-openjfx-docAUR java21-openjfx-srcAUR
OpenJFX 17 java17-openjfxAUR java17-openjfx-docAUR java17-openjfx-srcAUR
OpenJFX 11 java11-openjfxAUR java11-openjfx-docAUR java11-openjfx-srcAUR
OpenJFX 8 java8-openjfxAUR java8-openjfx-docAUR java8-openjfx-srcAUR

其他实现

  • AWS Corretto — 亚马逊网络服务的 OpenJDK 发行版。
https://aws.amazon.com/corretto/ || amazon-corretto-8AUR amazon-corretto-11AUR amazon-corretto-17AUR amazon-corretto-21-binAUR
  • Azul JDK — Azul 的 JDK 实现。 请注意,Azul Zulu Builds of OpenJDK 是开源的,而 Azul Zulu Prime Builds of OpenJDK 是商业产品,可免费用于开发和评估。
https://www.azul.com/downloads/ ||
Zulu: zulu-8-binAUR zulu-11-binAUR zulu-17-binAUR zulu-21-binAUR
Zulu Prime: jdk17-zulu-prime-binAUR
  • Eclipse Adoptium/Temurin — Eclipse 的 JRE/JDK 实现,基于 Hotspot JVM(以前称为 AdoptOpenJDK)。 请注意,JRE 被称为 Eclipse Temurin。
https://adoptium.net/ || jdk-temurinAUR jdk17-temurinAUR jdk11-temurinAUR
  • IBM Certified — IBM Semeru Runtime Certified Edition。
https://www.ibm.com/semeru-runtimes/downloads || jdk11-j9-binAUR
  • IBM J9 — IBM 的 JRE 实现,使用 OpenJ9 贡献。
https://www.ibm.com/support/pages/java-sdk-downloads || jdk8-j9-binAUR jdk7-j9-binAUR jdk7r1-j9-binAUR
  • Liberica JDK — BellSoft 的 Liberica JDK 实现。
https://bell-sw.com/libericajdk/ || liberica-jre-8-full-binAUR liberica-jdk-8-full-binAUR liberica-jre-11-binAUR liberica-jre-11-full-binAUR liberica-jdk-11-binAUR liberica-jdk-11-full-binAUR liberica-jdk-17-full-binAUR liberica-jdk-21-full-binAUR
  • Microsoft OpenJDK — 微软的 OpenJDK 发行版。
https://www.microsoft.com/openjdk/ || microsoft-openjdk-11-binAUR microsoft-openjdk-17-binAUR microsoft-openjdk-21-binAUR
  • OpenJ9 — Eclipse 的 JRE/JDK 实现,基于 IBM 贡献的 J9 JVM。
https://www.eclipse.org/openj9/ || jdk-openj9-binAUR jdk17-openj9-binAUR jdk11-openj9-binAUR jdk8-openj9-binAUR
  • Oracle JDK — Oracle 商业许可的 OpenJDK 构建版本。 请注意,某些版本只能通过手动下载获得,这需要签署 OTN 协议并创建 Oracle 帐户。
https://www.oracle.com/java/technologies/downloads/ ||
JRE: jreAUR jre-ltsAUR jre11AUR jre8AUR jre7AUR
JDK: jdkAUR jdk-ltsAUR jdk11AUR jdk8AUR jdk7AUR


提示: 32 位版本的 Oracle JDK 可以通过添加前缀 bin32- 找到,例如 bin32-jreAUR。 它们使用 java32-runtime-commonAUR,其功能类似于 java-runtime-common,方法是在后缀中添加 32,例如 java32。 同样的类比适用于 java32-environment-commonAUR,它仅供 32 位 JDK 软件包使用。

开发工具

对于集成开发环境,请参阅应用程序列表/实用程序#集成开发环境Java IDE 子章节。

为了阻止逆向工程,可以使用像 proguardAUR 这样的混淆器。

反编译器

  • CFR — Java 反编译器,支持 Java 9、10 和更高版本的现代功能。
https://www.benf.org/other/cfr/ || cfr
  • Fernflower — 用于 Java 的分析反编译器,作为 IntelliJ IDEA 的一部分开发。
https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine || fernflower-gitAUR
  • Vineflower — 从 Fernflower 分叉的 Java 反编译器,旨在提高代码质量。 也可用作 IntelliJ IDEA 插件。
https://github.com/Vineflower/vineflower || vineflowerAUR
  • Krakatau — Java 反编译器、汇编器和反汇编器。
https://github.com/Storyyeller/Krakatau || krakatau-gitAUR
  • Procyon decompiler — 实验性 Java 反编译器,灵感来自 ILSpy 和 Mono.Cecil。
https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler || procyon-decompiler
  • Java Decompiler (JD-Core) — 流行的 Java 反编译器,提供 GUI(请参阅 JD-GUI)并支持 Java 1-10。
https://java-decompiler.github.io/ || jd-core-javaAUR
  • Jadx — Android DEX 到 Java 反编译器,带有可选的 GUI(请参阅 Jadx-GUI)。
https://github.com/skylot/jadx || jadx
  • JAD — 未维护的 Java 反编译器(上次发布于 2006 年)。
https://varaneckas.com/jad || jad

图形界面前端

  • Bytecode Viewer — Java 逆向工程套件,包括反编译器、编辑器和调试器; CFR/Fernflower/Procyon 的前端。
https://bytecodeviewer.com || bytecode-viewerAUR
  • Recaf — 一种易于使用的现代 Java 字节码编辑器,可抽象出 Java 程序的复杂性; CFR/Fernflower/Procyon 的前端。
https://www.coley.software/Recaf/ || recaf-binAUR
  • Java Decompiler (JD-GUI) — 流行的 Java 反编译器,提供 GUI 并支持 Java 1-10; JD-Core 的前端。
https://java-decompiler.github.io/ || jd-guiAUR
  • Jadx-GUI — Android APK DEX 到 Java 反编译器,带有可选的 GUI; Jadx 的前端。
https://github.com/skylot/jadx || jadx
  • Luyten — 一个开源 Java 反编译器 GUI; Procyon 的前端。
https://github.com/deathmarine/Luyten || luytenAUR

在 JVM 之间切换

辅助脚本 archlinux-java(软件包 : java-runtime-common) 提供了此类功能

archlinux-java <COMMAND>

COMMAND:
status          List installed Java environments and enabled one
get             Return the short name of the Java environment set as default
set <JAVA_ENV>  Force <JAVA_ENV> as default
unset           Unset current default Java environment
fix             Fix an invalid/broken default Java environment configuration

列出已安装的兼容 Java 环境

$ archlinux-java status

示例

$ archlinux-java status
Available Java environments:
   java-11-openjdk (default)
   java-8-openjdk/jre

请注意 (default) 表示 java-11-openjdk 当前设置为默认值。 调用 java 和其他二进制文件将依赖于此 Java 安装。 另请注意,在之前的输出中,此处仅安装了 OpenJDK 8 的 JRE 部分。

更改默认 Java 环境

# archlinux-java set <JAVA_ENV_NAME>

示例

# archlinux-java set java-8-openjdk/jre
提示: 要查看可能的 <JAVA_ENV_NAME> 名称,请使用 archlinux-java status

请注意,archlinux-java 不允许您设置无效的 Java 环境。 在前面的示例中,jre8-openjdk 已安装,但 安装 jdk8-openjdk,因此尝试设置 java-8-openjdk 将会失败

# archlinux-java set java-8-openjdk
'/usr/lib/jvm/java-8-openjdk' is not a valid Java environment path

取消设置默认 Java 环境

应该不需要取消设置 Java 环境,因为提供它们的软件包应该会处理这个问题。 仍然,如果您想这样做,只需使用命令 unset

# archlinux-java unset

修复默认 Java 环境

如果设置了无效的 Java 环境链接,则调用 archlinux-java fix 命令会尝试修复它。 另请注意,如果未设置默认 Java 环境,这将查找有效的环境并尝试为您设置它。 官方支持的软件包“OpenJDK 8”将在此顺序中首先考虑,然后是其他已安装的环境。

# archlinux-java fix

使用非默认 Java 版本启动应用程序

如果您想使用与默认 Java 版本不同的 Java 版本启动应用程序(例如,如果您的系统上同时安装了版本 18(默认版本)和版本 11,并且您想使用 Java 11),您可以将您的应用程序包装在一个小的 shell 脚本中,以本地更改 Java 的默认路径

#!/bin/sh

export PATH="/usr/lib/jvm/java-11-openjdk/bin/:$PATH"
exec /path/to/application "$@"

对于 systemd 服务,您可以将 JAVA_HOME 附加到 drop-in 文件中的环境变量中

/etc/systemd/system/unit.d/override.conf
[Service]
Environment=JAVA_HOME=/usr/lib/jvm/java-11-openjdk

支持 archlinux-java 的软件包先决条件

注意: 此信息也适用于 archlinux32-java,用于 32 位 Java 软件包,在适用的情况下,软件包/可执行文件名中正确包含 32

本节针对希望在 AUR 中为备用 JVM 提供软件包并能够与 Arch Linux JVM 方案集成的打包者(即与 archlinux-java 兼容); 为此,软件包应

  • 将所有文件放在 /usr/lib/jvm/java-${JAVA_MAJOR_VERSION}-${VENDOR_NAME } 下
  • 确保为 java-runtime-commonjava-environment-common 提供链接的所有可执行文件都在相应的软件包中可用
  • 仅当从 /usr/bin 到可执行文件的链接不属于 java-runtime-commonjava-environment-common 时,才从 /usr/bin 运送链接
  • 为了防止冲突,man 手册页应附加 -${VENDOR_NAME}${JAVA_MAJOR_VERSION} 后缀 (参见 jre8-openjdk 文件列表,其中的 man 手册页附加了 -openjdk8 后缀)
  • 不要声明与其它 JDK、java-runtimejava-runtime-headlessjava-environment 的任何 冲突替换关系
  • 安装函数中使用脚本 archlinux-java 来设置 Java 环境为默认环境,前提是没有其它有效的 Java 环境已被设置(即:软件包不应强制安装为默认环境)。请参考 官方支持的 Java 环境软件包源以获取示例

另请注意

  • 需要任何 Java 环境的软件包应像往常一样声明对 java-runtimejava-runtime-headlessjava-environment 的依赖
  • 需要特定 Java 供应商的软件包应声明对相应软件包的依赖
  • OpenJDK 软件包现在声明 provides="java-runtime-openjdk=${pkgver}" 等。这使得第三方软件包能够声明对 OpenJDK 的依赖,而无需指定版本

故障排除

MySQL

由于 JDBC 驱动程序通常使用 URL 中的端口来建立与数据库的连接,因此即使它们可能在同一主机上运行,它也被认为是“远程”的(即,MySQL 不像其默认设置那样监听端口)。因此,要使用 JDBC 和 MySQL,您应该按照 MariaDB#Grant remote access 中的说明启用对 MySQL 的远程访问。

IntelliJ IDEA

如果 IntelliJ IDEA 在使用系统 Java SDK 路径时输出 The selected directory is not a valid home for JDK,您可能需要安装不同的 JDK 软件包并将其选为 IDEA 的 JDK。

模拟另一个窗口管理器

您可以使用来自 suckless.orgwmname 工具,使 JVM 认为您正在运行不同的窗口管理器。这可能解决 Java GUI 在 AwesomeDwmRatpoison 等窗口管理器中出现的渲染问题。这是因为 JVM 包含一个硬编码的已知非重父窗口管理器列表。更具讽刺意味的是,一些用户喜欢模拟 LG3D,这是由 Sun 用 Java 编写的非重父窗口管理器 Project Looking Glass。尝试设置 compizMetacityLG3D

$ wmname window_manager_name

在发出 wmname 命令后,您必须重启相关应用程序。

或者,可以使用 javaagent JavaMatePatch,它被创建用于在 MATE 中设置 WM 名称,并解决 Java Swing 应用程序在全屏启动时工作不正常的错误。添加 -javaagent:JavaMatePatch-1.0.0-SNAPSHOT.jar=window_manager_name 到 java 选项中使用它。

字体无法辨认

除了下面在 #更好的字体渲染 中提到的建议之外,某些字体之后可能仍然无法辨认。如果是这种情况,很可能是正在使用 Microsoft 字体。安装 ttf-ms-fontsAUR

某些应用程序中缺少文本

如果某些应用程序完全缺少文本,则使用 #提示和技巧 下的选项可能会有所帮助,如 FS#40871 中建议的那样。

灰色窗口、应用程序无法随窗口管理器调整大小、菜单立即关闭

标准 Java GUI 工具包有一个硬编码的“非重父”窗口管理器列表。如果使用列表中没有的窗口管理器,则运行某些 Java 应用程序可能会出现问题。最常见的问题之一是“灰色斑点”,即 Java 应用程序渲染为纯灰色框而不是渲染 GUI。另一个问题可能是菜单响应您的点击,但立即关闭。

有几种方法可能有所帮助

  • 参见 #模拟另一个窗口管理器
  • 设置 _JAVA_AWT_WM_NONREPARENTING=1 环境变量
  • 对于更高版本,设置 AWT_TOOLKIT=MToolkit 环境变量
  • 对于 xmonad,使用 SetWMName。但是,当同时使用 XMonad.Hooks.EwmhDesktops 时,其效果可能会被取消。在这种情况下,将 >> setWMName "LG3D" 附加到 LogHook 可能会有所帮助。

有关更多信息,请参见 Problems with Java applications, Applet java console

调试 JavaFX 应用程序时系统冻结

如果您的系统在调试 JavaFX 应用程序时冻结,您可以尝试提供 JVM 选项 -Dsun.awt.disablegrab=true

参见 https://bugs.java.com/bugdatabase/view_bug?bug_id=6714678

JavaFX 的 MediaPlayer 构造函数抛出异常

从 JavaFX 的声音模块创建 MediaPlayer 类的实例可能会抛出以下异常(Oracle JDK 和 OpenJDK 均是如此)

... (i.e. FXMLLoader construction exceptions) ...
Caused by: MediaException: UNKNOWN : com.sun.media.jfxmedia.MediaException: Could not create player! : com.sun.media.jfxmedia.MediaException: Could not create player!
 at javafx.scene.media.MediaException.exceptionToMediaException(MediaException.java:146)
 at javafx.scene.media.MediaPlayer.init(MediaPlayer.java:511)
 at javafx.scene.media.MediaPlayer.<init>(MediaPlayer.java:414)
 at <constructor call>
...

这是 JavaFX 与 Arch Linux 存储库中提供的现代 ffmpeg 构建版本之间存在一些不兼容性的结果。

可行的解决方案是安装 ffmpeg-compat-55AUR。或者,如果之前的版本构建失败,安装 ffmpeg3.4AUR 可能会起作用。

参见 https://www.reddit.com/r/archlinux/comments/70o8o6/using_a_javafx_mediaplayer_in_arch/

Java 应用程序无法打开外部链接

如果 Java 应用程序无法打开链接,例如您的 Web 浏览器,请安装 gvfs。这是 Desktop.Action.BROWSE 方法所必需的。参见 [1] 打印错误消息 java.lang.UnsupportedOperationException: The BROWSE action is not supported on the current platform! 的应用程序是此问题的可靠指标。

初始化 QuantumRenderer 时出错:未找到合适的管道

可能的问题/解决方案

提示和技巧

注意: 本节中的建议适用于所有应用程序,使用显式安装(外部)的 Java 运行时环境。某些应用程序捆绑了自己的(私有)运行时环境或使用自己的 GUI、字体渲染等机制,因此以下任何内容都不能保证有效。

大多数 Java 应用程序的行为可以通过向 Java 运行时提供预定义的变量来控制。根据 这个论坛帖子,一种方法是在您的 ~/.bash_profile (或 /etc/profile.d/jre.sh,以影响未通过 source ~/.bash_profile 运行的程序) 中添加以下行

export JDK_JAVA_OPTIONS="-D<option 1> -D<option 2>..."

例如,要使用系统抗锯齿字体并使 Swing 使用 GTK 外观

export JDK_JAVA_OPTIONS='-Dawt.useSystemAAFontSettings=on -Dswing.aatext=true -Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel'

存在三个这样的变量,稍后在下表中解释的选项具有优先级。

JAVA_TOOL_OPTIONS 影响应用程序以及 javacjshell 等工具。
JDK_JAVA_OPTIONS 影响应用程序(所有通过 java 命令启动的内容)。需要 Java 9。
(命令行选项) 在“类名”参数之前指定的参数是 Java 选项。
_JAVA_OPTIONS 旧方法,影响应用程序和工具。

更好的字体渲染

众所周知,Java 的闭源和开源实现都存在字体抗锯齿实现不正确的问题。这可以通过以下选项修复:-Dawt.useSystemAAFontSettings=on, -Dswing.aatext=true

有关更多详细信息,请参见 Java 运行时环境字体

静默命令行上的 'Picked up JDK_JAVA_OPTIONS' 消息

设置 JDK_JAVA_OPTIONS 环境变量会使 java (openjdk) 向 stderr 写入 'Picked up JDK_JAVA_OPTIONS=...' 形式的消息。要在您的终端中抑制这些消息,您可以取消设置 ~/.bashrc 中的环境变量,并将 java 别名设置为将相同的选项作为命令行参数传递

SILENT_JAVA_OPTIONS="$JDK_JAVA_OPTIONS"
unset JDK_JAVA_OPTIONS
alias java='java "$SILENT_JAVA_OPTIONS"'

非交互式 shell,例如 Java 程序的启动器脚本,(通常)不读取 ~/.bashrc,但仍然从其父进程继承导出的变量(父进程又在某个时候从读取 ~/.bash_profile 的登录 shell 中继承了这些变量)。至于它们读取 ~/.bashrc 的情况,通常会在 ~/.bashrc 的顶部放置一个语句以避免读取该文件。这样,变量会传递给通过桌面菜单启动的程序,并且在交互式 shell 的情况下,消息会干扰别名,因此使用别名代替(别名又不能在脚本中使用)。

GTK 外观

如果您的 Java 程序看起来很丑陋,您可能需要为 Swing 组件设置默认的外观

swing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel

某些 Java 程序坚持使用跨平台的 Metal 外观。在某些情况下,您可以通过设置以下属性强制这些应用程序使用 GTK 外观

swing.crossplatformlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel

GTK3 支持

在 Java 9 之前的版本中,GTK LookAndFeel 是链接到 GTK2 的,而许多较新的桌面应用程序使用 GTK3。GTK 版本之间的这种不兼容性可能会破坏使用带有 GUI 的 Java 插件的应用程序,因为在同一进程中混合使用 GTK2 和 GTK3 是不受支持的(例如,LibreOffice 5.0)。

GTK LookAndFeel 可以针对 GTK 版本 22.23 运行,默认为 GTK3。这可以通过设置以下属性来覆盖

jdk.gtk.version=2.2

HiDPI

根据 GUI 框架,可以使用不同的方法启用 HiDPI#Java applications

更好的 2D 性能

切换到基于 OpenGL 的硬件加速管道将提高 2D 性能

export JDK_JAVA_OPTIONS='-Dsun.java2d.opengl=true'
注意: 启用此选项可能会导致 JetBrains IDE 等软件的 UI 行为异常,使其部分绘制窗口、弹出窗口和工具栏。