Java (简体中文)

From ArchWiki

Tango-preferences-desktop-locale.pngThis article or section needs to be translated.Tango-preferences-desktop-locale.png

Notes: Some sentences are still in English. (Discuss in Talk:Java (简体中文))
翻译状态:本文是 Java翻译。上次翻译日期:2022-06-07。如果英文版本有所更改,则您可以帮助同步翻译。

摘自维基百科中的 Java 词条:

Java是一种编程语言,最初由Sun Microsystems开发,并于1995年作为Sun Microsystems的Java平台的核心组件发布。它有很多语法来自C和C++,但对象模型更简洁,底层组件更少。Java的应用一般会编译成能在任何Java虚拟机(JVM)而不是特定架构上运行的字节码。

Arch Linux官方支持开源的第7、8、11和17版的 OpenJDK。这些JVM可以并存,并能够通过帮助脚本archlinux-java切换。在 AUR中也有一些不受官方支持的Java环境。

安装

注意:
  • Arch Linux官方只支持 OpenJDK 实现。
  • 刚安装完成的Java环境还无法被Shell($PATH 变量)识别。可以在命令行中使用source命令读取/etc/profile,重启,或者注销并重新登入桌面环境来正确更新。

两个常见的包经常作为其它包的依赖,分别是 java-runtime-common (包含Java运行环境(JRE)的公共文件) 和 java-environment-common (包括Java开发包(JDK)的公共文件)。包提供的环境配置文件 /etc/profile.d/jre.sh 指向由 archlinux-java 帮助脚本设置的链接 /usr/lib/jvm/default/bin

警告: 务必使用 archlinux-java编辑 /usr/lib/jvm/default/usr/lib/jvm/default-runtime 这两个链接。

这些链接用来指示位于 /usr/lib/jvm/java-${JAVA_MAJOR_VERSION}-${VENDOR_NAME} 的默认Java运行环境,或位于 /usr/lib/jvm/java-${JAVA_MAJOR_VERSION}-${VENDOR_NAME}/jre 的Java运行环境。

大多数安装的可执行文件都以链接的形式放在 /usr/bin 中,其他可执行文件则在 $PATH 指向的位置处。/etc/profile.d/jdk.sh 已经不再在包中提供了。

OpenJDK

OpenJDK是Java平台标准版(Java SE)的开源实现,也是官方的参考实现。有几个OpenJDK构建的分发,如Adoptium(以前称为AdvertOpenJDK)和Amazon Corretto。Arch Linux的OpenJDK包由上游的OpenJDK源代码构建。

Headless JRE
Java的最小运行环境 - 执行非GUI的Java程序所需。
Full JRE
完全的Java运行环境 - 执行Java GUI程序所需,依赖于headless JRE。
JDK
Java Development Kit - Java开发所需,依赖于 full JRE。
版本 Headless JRE Full JRE JDK 文献 源码
OpenJDK 17 jre-openjdk-headless jre-openjdk jdk-openjdk openjdk-doc openjdk-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

OpenJDK GA — Latest OpenJDK General-Availability Release build from Oracle.

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

OpenJDK EA — Latest OpenJDK Early-Access build for development version from Oracle.

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

IcedTea-Web — Java Web Start and the deprecated Java browser plugin.

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

OpenJFX

OpenJFX is the open-source implementation of JavaFX. You do not need to install this package if you are using Oracle JDK. This package only concerns users of the open source implementation of Java (OpenJDK project), and its derivatives.

版本 运行环境与开发 文档 源码
OpenJFX 18 java-openjfx java-openjfx-doc java-openjfx-src
OpenJFX 17 java17-openjfx java17-openjfx-doc java17-openjfx-src
OpenJFX 11 java11-openjfx java11-openjfx-doc java11-openjfx-src
OpenJFX 8 java8-openjfxAUR java8-openjfx-docAUR java8-openjfx-srcAUR

OpenJFX GA — Latest OpenJFX General-Availability Release build from Gluon.

https://openjfx.io/ || java-openjfx-binAUR

OpenJFX EA — Latest OpenJFX Early-Access build for development version from Gluon.

https://openjfx.io/ || java-openjfx-ea-binAUR

其他实现

Oracle JDK — Oracle's commercially licensed build of OpenJDK.Note that some versions are only available via manual download, which requires to sign the OTN agreement and create an Oracle account.

https://www.oracle.com/java/technologies/downloads/ ||

Eclipse Adoptium/Temurin — Eclipse's implementation of JRE/JDK, based on the Hotspot JVM (formerly AdoptOpenJDK). Note that the JRE is known as Eclipse Temurin.

https://adoptium.net/ || jdk-temurinAUR jdk17-temurinAUR jdk11-temurinAUR

OpenJ9 — Eclipse's implementation of JRE, contributed by IBM.

https://www.eclipse.org/openj9/ || jdk-openj9-binAUR jdk14-openj9-binAUR jdk13-openj9-binAUR jdk12-openj9-binAUR jdk11-openj9-binAUR jdk10-openj9-binAUR jdk9-openj9-binAUR jdk8-openj9-binAUR

IBM Certified — IBM Semeru Runtime Certified Edition.

https://www.ibm.com/semeru-runtimes/downloads || jdk11-j9-binAUR

IBM J9 — IBM's implementation of JRE, using OpenJ9 contributions.

https://www.ibm.com/support/pages/java-sdk-downloads || jdk8-j9-binAUR jdk7-j9-binAUR jdk7r1-j9-binAUR

Parrot VM — a VM with experimental support for Java [1] through two different methods: either as a Java VM bytecode translator, or as a Java compiler targeting the Parrot VM. Parrot is not actively developed since 2017.

http://www.parrot.org/ || parrotAUR
Note: Oracle JDK的32位版本可以通过前缀bin32-找到,如bin32-jreAUR。其使用java32-runtime-commonAUR,功能与java-runtime-common相同,但添加了32的后缀,如java32java32-environment-commonAUR也是同理,只有32位的JDK包使用它。

开发工具

对于集成开发环境,见List of applications#Integrated development environmentsJava IDEs子分区。

为了阻止逆向工程,可以使用proguardAUR等混淆器。

反编译器

  • CFR — Java decompiler, supporting modern features of Java 9, 10 and beyond.
https://www.benf.org/other/cfr/ || cfrAUR
  • Fernflower — Analytical decompiler for Java, developed as part of IntelliJ IDEA.
https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine || fernflower-gitAUR
  • Krakatau — Java decompiler, assembler, and disassembler.
https://github.com/Storyyeller/Krakatau || krakatau-gitAUR
  • Procyon decompiler — Experimental Java decompiler, inspired by ILSpy and Mono.Cecil.
https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler || procyon-decompilerAUR
  • Java Decompiler (JD-Core) — Popular Java decompiler providing a GUI (see JD-GUI) and supporting Java 1-10.
https://java-decompiler.github.io/ || jd-core-javaAUR
  • Jadx — Android DEX to Java decompiler with an optional GUI (see Jadx-GUI)
https://github.com/skylot/jadx || jadx
  • JAD — Unmaintained Java decompiler (last release 2006).
https://varaneckas.com/jad || jad

GUI前端

  • Bytecode Viewer — Java reverse engineering suite, including a decompiler, editor and debugger; Frontend for CFR/Fernflower/Procyon
https://bytecodeviewer.com || bytecode-viewerAUR
  • Recaf — An easy to use modern Java bytecode editor that abstracts away the complexities of Java programs; Frontend for CFR/Fernflower/Procyon
https://www.coley.software/Recaf/ || recaf-binAUR
  • Java Decompiler (JD-GUI) — Popular Java decompiler providing a GUI and supporting Java 1-10; Frontend for JD-Core
https://java-decompiler.github.io/ || jd-guiAUR
  • Jadx-GUI — Android APK DEX to Java decompiler with an optional GUI; Frontend for Jadx
https://github.com/skylot/jadx || jadx
  • Luyten — An Open Source Java Decompiler Gui; Frontend for Procyon
https://github.com/deathmarine/Luyten || luytenAUR

在JVM间切换

帮助脚本 archlinux-java 提供了如下功能:

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-7-openjdk (default)
  java-8-openjdk/jre

这里的(default)表示目前默认使用java-7-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),可以用一个bash脚本包装应用程序,在本地改变Java的默认路径。例如默认版本是Java 18,而您要使用java 11:

#!/bin/sh 

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

For a systemd service you can append JAVA_HOME to environment variables in the drop-in file:

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

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

注意: 这条信息同样适用于 archlinux32-java 的32位Java包,如果它们的包或者可执行名字里有 32 ,都可适用.

这个分区的信息针对愿意提供包作为备份JVM给 AUR 的贡献者, 并且能够用 archlinux-java集成Arch Linux JVM方案。如果要这样的话,这些包应该:

同时也要注意:

  • 包需要的任何Java环境都应声明依赖,和通常一样在java-runtimejava-runtime-headlessjava-environment里声明。
  • 包如果需要特定的Java提供商,应该在相关包里声明依赖。
  • OpenJDK 包现在应该声明 provides="java-runtime-openjdk=${pkgver}" 等。这能让第三方的包在没有特定版本要求的OpenJDK里声明依赖

疑难解答

MySQL

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

IntelliJ IDEA

如果在设置JDK的时候选择了系统的JDK,同时碰到了错误提示The selected directory is not a valid home for JDK,此时应重新安装另一个JDK包,并在IDEA设置中选择它。

伪装成另一个窗口管理器

可以使用suckless.org中的wmname来使JVM相信其正运行于其它窗口管理器。这也许能解决在AwesomeDwmRatpoison等窗口管理器中出现的Java GUI渲染问题。尝试设置 "compiz "或 "LG3D":

$ wmname LG3D

运行了这条命令后,必须重启有问题的程序。

这种做法能够有效,是因为JVM包含了一个已知的、non-re-parenting窗口管理器的硬编码列表。

javaagent 是一个在 MATE 中看设置 wmname 的工具,可以解决 Java 程序全屏显示失败的问题。

字体难以辨认

除了下面#更好的字体渲染中的建议,有些字体可能依然难以辨认。使用微软的字体或许能有所改善,安装ttf-ms-fontsAUR即可。

某些应用没有文字

如果某些应用完全没有文字,使用FS#40871中建议的#提示和技巧下的选项可能会有所帮助。

灰色窗口/应用不随窗口管理器调整大小/菜单自动关闭

标准的Java GUI工具包有一个non-re-parenting窗口管理器的硬编码列表,如果使用不在该列表中的窗口管理器,在运行某些Java应用时可能会有问题。最常见的问题之一是Java应用渲染成了一个灰色盒子而不是GUI。另一个问题是菜单能够响应点击,但马上又会关闭。

以下内容也许有所帮助:

  • #伪装成另一个窗口管理器
  • 对于jre8-openjdk,在/etc/profile.d/jre.sh中添加一行export _JAVA_AWT_WM_NONREPARENTING=1,然后重新登录系统。
  • 对于最新版本的JDK,执行窗口管理器之前,在~/.xinitrc中添加一行export AWT_TOOLKIT=MToolkit
  • 对于Oracle的JRE/JDK,使用SetWMName,但当同时使用XMonad.Hooks.EwmhDesktops时可能无效。这种情况下,在>> setWMName "LG3D"中添加LogHook可能会有帮助。
  • 对于swayexport _JAVA_AWT_WM_NONREPARENTING=1可能可以解决问题。

详见[2]

调试JavaFX应用时系统卡住

如果调试JavaFX应用时系统卡住了,可以尝试提供JVM选项-Dsun.awt.disablegrab=true

[3]

JavaFX's MediaPlayer constructor throws an exception

从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以解决问题。

[4]

Java程序无法打开外部链接

如果Java应用无法将链接打开到浏览器等应用,请安装gvfs,因为Desktop.Action.BROWSE办法依赖于它。

[5]

Error initializing QuantumRenderer: no suitable pipeline found

可能的问题和解决方法:

提示和技巧

注意: 本节中的建议适用于所有使用明确安装(外部)的Java运行环境的应用。有些应用捆绑了自己(私有)的运行环境,或使用自己的GUI、字体渲染等机制,以下内容不一定完全适用于这种情况。

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

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

例如,使用系统抗锯齿字体并使swing使用GTK的外观与体验(look and feel):

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

存在三个这样的变量,在下表中解释的选项优先考虑。

JAVA_TOOL_OPTIONS 影响应用程序以及javac、jshell等工具。
JDK_JAVA_OPTIONS 影响通过java命令启动的一切应用程序,需要Java 9。
(命令行选项) 在 "class name"参数前指定的参数是Java选项。
_JAVA_OPTIONS 旧方法,影响应用程序和工具。

更好的字体渲染

开源和闭源的Java实现都有不合适的抗锯齿字体实现。这可以通过以下办法来解决: -Dawt.useSystemAAFontSettings=on-Dswing.aatext=true

详见Java Runtime Environment fonts

禁止命令行里的 'Picked up _JAVA_OPTIONS' 消息

设置 JDK_JAVA_OPTIONS 环境变量会使Java(openjdk)向stderr写出以下形式的信息:'Picked up JDK_JAVA_OPTIONS=...'。为了禁止终端中显示这些信息,可以在~/.bashrc中取消设置环境变量,并alias java,将这些选项传递为命令行参数:

_SILENT_JAVA_OPTIONS="$_JAVA_OPTIONS"
unset _JAVA_OPTIONS
alias java='java "$_SILENT_JAVA_OPTIONS"'

非交互式的Shell,如Java程序的启动脚本,(通常)不读取~/.bashrc,但仍从其父进程中继承了导出的变量(而父进程又在某个时间从读取了~/.bash_profile的登录Shell中继承了它)。

至于这种情况,一般会在~/.bashrc的开头放一个声明,以避免读取文件。这样变量就会传递到通过桌面菜单启动的程序,如果是交互式Shell,则会使用alias来代替(这则不能用于脚本)。

GTK LookAndFeel(外观与体验)

如果你的Java程序看起来很丑,你可能想为swing组件设置默认外观与体验:

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

一些Java程序坚持用跨平台的金属风格外观与体验。在这些情况下,你可以通过设置下面的属性强制这些app用GTK外观和外观:

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

GTK3支持

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

GTK LookAndFeel可以针对GTK22.23运行,默认为GTK3。可以修改以下属性以调整。

jdk.gtk.version=3

HiDPI

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

更好的2D性能

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

export _JAVA_OPTIONS='-Dsun.java2d.opengl=true'
注意: 启用该选项可能会导致像JetBrains IDEs这样的软件的UI出现问题,如只绘制部分绘制窗口、弹出窗口和工具栏。

另见