Java (简体中文)
摘自维基百科中的 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。
OpenJDK GA — Latest OpenJDK General-Availability Release build from Oracle.
OpenJDK EA — Latest OpenJDK Early-Access build for development version from Oracle.
IcedTea-Web — Java Web Start and the deprecated Java browser plugin.
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 GA — Latest OpenJFX General-Availability Release build from Gluon.
OpenJFX EA — Latest OpenJFX Early-Access build for development version from Gluon.
其他实现
Oracle JDK — Oracle's commercially licensed build of OpenJDK.
- https://www.oracle.com/technetwork/java/javase/downloads/index.html || jreAUR jre12AUR jre11AUR jre10AUR jre9AUR jre8AUR jre7AUR jre6AUR jdkAUR jdk12AUR jdk11AUR jdk10AUR jdk9AUR jdk8AUR jdk7AUR jdk6AUR jdk-develAUR
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.
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
bin32-
找到,如bin32-jreAUR。其使用java32-runtime-commonAUR,功能与java-runtime-common相同,但添加了32
的后缀,如java32
。java32-environment-commonAUR也是同理,只有32位的JDK包使用它。开发工具
对于集成开发环境,见List of applications#Integrated development environments 和Java IDEs子分区。
为了阻止逆向工程,可以使用proguardAUR等混淆器。
反编译器
- CFR — Java decompiler, supporting modern features of Java 9, 10 and beyond.
- 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.
- Procyon decompiler — Experimental Java decompiler, inspired by ILSpy and Mono.Cecil.
- Java Decompiler (JD-Core) — Popular Java decompiler providing a GUI (see JD-GUI) and supporting Java 1-10.
- Jadx — Android DEX to Java decompiler with an optional GUI (see Jadx-GUI)
- JAD — Unmaintained Java decompiler (last release 2006).
GUI前端
- Bytecode Viewer — Java reverse engineering suite, including a decompiler, editor and debugger; Frontend for CFR/Fernflower/Procyon
- Recaf — An easy to use modern Java bytecode editor that abstracts away the complexities of Java programs; Frontend for CFR/Fernflower/Procyon
- Java Decompiler (JD-GUI) — Popular Java decompiler providing a GUI and supporting Java 1-10; Frontend for JD-Core
- Jadx-GUI — Android APK DEX to Java decompiler with an optional GUI; Frontend for Jadx
- Luyten — An Open Source Java Decompiler Gui; Frontend for Procyon
在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方案. 如果要这样的话,这些包应该:
- 把所有文件放在
/usr/lib/jvm/java-${JAVA_MAJOR_VERSION}-${VENDOR_NAME}
- 确认所有的 java-runtime-common 和 java-environment-common 提供的可执行链接在相关包里都可用
- 把所有链接从
/usr/bin
移动到可执行文件里, 除非这些链接不属于 java-runtime-common 和 java-environment-common - 用
-${VENDOR_NAME}${JAVA_MAJOR_VERSION}
的格式给手册页添加后缀 (查阅 jre8-openjdk file list 它的手册页用-openjdk8
做后缀) - 不要定义任何 冲突 和替代 ,用其他的JDK,
java-runtime
,java-runtime-headless
和java-environment
- 在安装函数 里使用
archlinux-java
脚本以将Java环境设置为默认 如果没有其他可用的Java环境准备设置的话 (即: 这些包不应该 强制 被装为默认). 查阅 officially supported Java environment package sources 做例子
同时也要注意:
- 包需要的任何Java环境都应声明依赖,和通常一样在
java-runtime
、java-runtime-headless
或java-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相信其正运行于其它窗口管理器。这也许能解决在Awesome或Dwm或Ratpoison等窗口管理器中出现的Java GUI渲染问题。尝试设置 "compiz "或 "LG3D":
$ wmname LG3D
运行了这条命令后,必须重启有问题的程序。
这种做法能够有效,是因为JVM包含了一个已知的、non-re-parenting窗口管理器的硬编码列表。
字体难以辨认
除了下面#更好的字体渲染中的建议,有些字体可能依然难以辨认。使用微软的字体或许能有所改善,安装ttf-ms-fontsAUR即可。
某些应用没有文字
如果某些应用完全没有文字,使用FS#40871中建议的#Tips and tricks下的选项可能会有所帮助。
灰色窗口/应用不随窗口管理器调整大小/菜单自动关闭
标准的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
可能会有帮助。 - 对于sway,
export _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
可能的问题和解决方法:
- 没有GTK2。安装gtk2。
- 没有OpenJFX。安装java-openjfx。
提示和技巧
大多数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的开源还是闭源实现,其中都有字体抗锯齿不恰当的问题,可以通过以下选项解决:-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可以针对GTK2
、2.2
和3
运行,默认为GTK3。可以修改以下属性以调整。
jdk.gtk.version=3
HiDPI
根据GUI框架的不同,HiDPI#Java applications可以使用不同的方法启用。
更好的2D性能
切换到基于OpenGL的硬件加速管道可以提高2D性能:
export _JAVA_OPTIONS='-Dsun.java2d.opengl=true'