前言
这两天开始读深入理解 Java 虚拟机了。在这本书的第一章就提到了动手编译 OpenJDK。 突然想到 2018 年 11 月被 OpenCV 的交叉编译支配的恐惧。
网上的各种攻略琳琅满目,五花八门。
终于,在蹚了前人的那些坑之后,我成功编译了 OpenJDK 8。其实编译一个 JDK 也没那么难。
– 即使是 2020 年,在更新策略激进的 Arch 系 Linux 下,我没有降级任何软件也照样编译成功。
注:本篇文章以 Manjaro Linux 为例进行讲解。其它的 Linux 基本一致,只是软件包名不同。
准备
环境
名称 | 版本 |
---|---|
OS | Manjaro 20.0 Lysia |
Kernel | x86_64 Linux 4.19.118-1-MANJARO |
make | GNU Make 4.3 x86_64-pc-linux-gnu |
GCC | gcc (Arch Linux 9.3.0-1) 9.3.0 |
注:我并没有切换到低版本的 gcc。
OpenJDK 8
你需要一个 OpenJDK 8 来编译 OpenJDK 8 原代码中的 Java 代码。太高或太低都不能编译成功。
注: OpenJDK 7 理论上可以,但编译时会出问题。还是建议用 OpenJDK 8。
在 Arch Linux/Manjaro Linux 下,可以通过archlinux-java status
查看是否有 OpenJDK 8。输入以下命令:
$ archlinux-java status | grep 8
java-8-openjdk
如果没有的话(即上面命令没有结果),赶紧去搞一个!(sudo pacman -S jdk8-openjdk
)
Mercurial
作为 OpenJDK 的版本管理系统,类似于 git。
在 Arch Linux 下可以通过 sudo pacman -S mercurial
安装。
(直接连接会很慢,请自行准备工具,具体工具请自行探索,支持 HTTP 代理就可以。下文会讲解如何给 mercurial 套 HTTP 代理。)
注:本篇文章中提到的所有 sudo 操作都已经特别指出,不要在 sudo 模式下进行其它操作。
GCC 和 make
这个貌似不用我多说。这个年头用 Linux 写代码,没个 gcc
和 make
好像还是一件挺尴尬的事情。
(还是说一句:make 不是系统自带的,gcc 大多数自带,缺什么装什么。)
编译
以上的工具准备好了,就可以开始编译了。
clone
正常下载是hg clone 目标网址
。如果你的网络环境不好,可以出动 HTTP 代理。下例是让 mercurial 经过 http://127.0.0.1:8000/ 处的代理:
hg --config http_proxy.host=127.0.0.1:8000 clone http://hg.openjdk.java.net/jdk8u/jdk8u/
get_source
如果你的网络环境不好,我们要预先定义一下代理:
export HGFOREST_GLOBALOPTS=" --config http_proxy.host=127.0.0.1:8000"
注意:在
--config
前有一个空格。
开始吧:
chmod +x ./get_source.sh
./get_source.sh
如果中间失败,可以重复运行get_source.sh
,脚本会从失败的地方继续下载。
注意:有些地方提到可以去 http://jdk.java.net/ 下载。但是我这里下载到的源代码都不能正常编译。
configure
输入以下命令开始配置工作。这里需要手动指定 Bootstrap JDK 的路径。
./configure --with-boot-jdk=/usr/lib/jvm/java-8-openjdk
如果没有报错,那么说明你的环境配置正常。
dirty hack
我们还需要更改一下编译参数。OpenJDK 默认编译的时候会将所有 warning
视为 error
,会导致以下错误:cc1plus: all warnings being treated as errors
因为 OpenJDK 8 的编译不支持 --disable-warnings-as-errors
参数,所以我们需要手动修改一下:
打开./hotspot/make/linux/makefiles/gcc.make
,然后找到 WARNINGS_ARE_ERRORS =
,前面加#
,把这行注释掉。
make
最后,可以正式编译了,分情况讨论。
注:不需要指定 CPU 核心数。默认编译就是多核。
仅编译
如果只编译,不想要二进制:输入make
命令,开始编译。
当你看到以下信息时,你就成功了:
## Finished jdk (build time 00:01:43)
----- Build times -------
Start 2020-05-05 13:14:42
End 2020-05-05 13:20:26
00:00:13 corba
00:03:23 hotspot
00:00:08 jaxp
00:00:11 jaxws
00:01:43 jdk
00:00:06 langtools
00:05:44 TOTAL
-------------------------
编译二进制
如果你想编译出 JDK JRE 的那套二进制的话,请运行make images
。
此时结果应该是这样的:
## Finished images (build time 00:01:28)
----- Build times -------
Start 2020-05-05 19:36:50
End 2020-05-05 19:38:49
00:00:00 corba
00:00:16 demos
00:00:00 hotspot
00:01:28 images
00:00:01 jaxp
00:00:00 jaxws
00:00:05 jdk
00:00:01 langtools
00:00:08 nashorn
00:01:59 TOTAL
-------------------------
这种情况下,你可以在./build/linux-x86_64-normal-server-release/images/j2sdk-image/bin/
目录下找到java
和javac
。
你可以运行一下:
$ ./java -version
openjdk version "1.8.0-internal"
OpenJDK Runtime Environment (build 1.8.0-internal-amazingrise_2020_05_05_13_13-b00)
OpenJDK 64-Bit Server VM (build 25.71-b00, mixed mode)
没错,它的版本号里写着你的机器名。 很有成就感。
最后
结语
真的就这些了吗?是的,就这些。在 Linux 上,书上那一长串的export
统统不需要。
而且可以看出,在我的普普通通的笔记本上,不设置任何参数也可以很快完成编译。网上和书上的各种优化大可不必,configure
已经帮我们做好大部分了。
尽信书不如无书。
有人可能会说这篇文章很水,但实际上我花了很多时间:我编译过 OpenJDK 7, 9, 11, 14,试了网上各种各样的方法都不行。
就是希望后人少走点弯路吧(不走是不可能的)。
另外,网上有人说,OpenJDK 8 编译巨坑,其实也没那么复杂。(可能因为他是 macOS?)
网上还有人说,怎么编译都不成功,把 Ubuntu 换成 CentOS 才行。我想说,真的不至于。
参考
《深入理解 Java 虚拟机》周志明著,第二版。
问题整理 [已解决] - Debian10 下编译 OpenJDK-8 源码 - cc1plus: all warnings being treated as errors
–disable-warnings-as-errors does not work for HotSpot build
次回予告
下次可能是 NES 模拟器
或者简单 NLP 问答机器人
的实现了,看我有没有时间吧。
上次修改於 2020-05-05