1.系统需求
本文使用Windows11 + [WSL2](什么是适用于 Linux 的 Windows 子系统 | Microsoft Learn),在WSL2中运行Ubuntu18.04作为系统构建OpenJDK,因为使用Linux或MacOS上构建工具链和依赖项上比在Windows上更容易。
本次编译中采用得是64位操作系统,默认参数下编译出来的也是64位的OpenJDK,如果需要编译32位的版本,同样推荐在64位的机器上进行,因为编译过程中可以使用更大的内存(32位系统受4G内存限制),通过编译参数(--with-target-bits=32
)来指定需要生成32位编译结果即可。在官方文档上要求编译OpenJDK需要至少2-4GB的内存空间,6-8GB的磁盘空间。虽然OpenJDK的源码只有不到600MB,但是编译过程会产生大量的中间文件,并且编译出不同优化级别(Product、FastDebug、SlowDebug)的HotSpot虚拟机可能要重复生成这些中间文件。
2.获取源码
源码链接:https://hg.openjdk.org/jdk/jdk12
点击左侧菜单中的zip,可以下载当前版本打包好的源代码。
点击左侧菜单中的browse,可以看到源码的根目录页面。
3.构建编译环境
3.1 安装GCC
首先查看Ubuntu系统中的GCC版本,确保GCC版本不低于4.8,官方推荐使用GCC 7.8,但是也不建议GCC版本太高。
# 查看gcc/g++版本
gcc -v
# 查看系统已有的版本
ls /usr/bin/gcc*
Ubuntu18.04中的GCC版本为7.5,我们就使用这个。如果你的系统上没有GCC,可以使用以下命令安装GCC:
# 安装 "build-essential" 软件包,
# 会自动安装 GNU 编译器 (GCC)、GNU make、libc-dev 和其他必要的开发工具和库,
# 确保你能够编译和构建源代码程序
sudo apt-get install build-essential
如果你只想单独安装GCC编译器,可以使用以下命令:
sudo apt-get install gcc
# 如果想指定安装版本,例如指定GCC版本为7
# sudo apt-get install gcc-7
如果有多个版本的GCC,想要在多版本之间切换
- 先将需要的版本添加到update-alternatives中。例如,在命令
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 50
中,数字50
表示正在安装的备选项的优先级。update-alternatives
命令用于管理指向提供类似功能的不同程序的符号链接。在这种情况下,它用于管理gcc
编译器的符号链接。优先级值用于确定默认情况下应使用哪个备选项,当有多个备选项可用时。更大的值表示更高的优先级。在这种情况下,gcc-5
的优先级为 50,gcc-7
的优先级为 70这意味着在Auto mode
下将优先选择gcc-7
。
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 50
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 70
- 手动配置update-alternatives
sudo update-alternatives --config gcc
3.2 安装依赖库
工具 | 库名称 | 安装命令 |
FreeType | The FreeType Project |
|
CUPS | Common UNIX Printing System |
|
X11 | X Window System |
|
ALSA | Advanced Linux Sound Architecture |
|
libffi | Protable Foreign Function Interface Library |
|
Autoconf | Extensible Package of M4 Macros |
|
3.3 安装Bootstrap JDK
假设要编译大版本号为的JDK,我们要另外准备一个大版本号为
的、已经编译好的JDK,这是因为OpenJDK由多个部分(HotSpot、JDK类库、JAXWS…)组成,其中一部分(HotSpot)代码使用C、C++编写,而更多的代码则是使用Java来实现,因此编译这些Java代码就要用到JDK,官方称这个JDK为“Bootstrap JDK”。例如,编译OpenJDK 12时,Bootstrap JDK必须使用JDK11及之后的版本。
在Ubuntu中安装OpenJDK 11的命令如下:
sudo apt-get install openjdk-11-jdk
4.编译
需要下载的编译环境和依赖项目都齐备后,我们就可以按照默认配置来开始编译了。但通常我们编译OpenJDK的目的都不仅仅是为了得到在自己机器中诞生的编译成品,而是带着调试、定制化等需求,这样就必须了解OpenJDK提供的编译参数才行。
一些编译参数:
编译参数 | 说明 |
–with-debug-level=<level> | 设置编译级别,可选值为release、fastdebug、slowdebug,越往后进行的优化措施就越少,带的调试信息就越多。默认模式为release。 |
–enable-debug | 等效于–with-debug-level=fastdebug。 |
–with-native-debug-symbols=<method> | 确定调试符号信息的编译方式,可选值为none、internal、external、zipped。 |
–with-version-string=<string> | 设置编译JDK的版本号,例如java -version的输出就会显示该信息。 |
–with-jvm-variants=<variant>[,<variant>…] | 编译特定模式的HotSpot虚拟机,可以多个模式并存,可选值为server、client、minimal、core、zero、custom。 |
–with-target-bits=<bits> | 指明要编译32位还是64位的Java虚拟机。 |
–with-conf-name=<name> | 指定编译配置名称,默认根据编译的操作系统、指令集架构、调试级别自动生成一个配置名称。例如,linux-x86_64-server-release。 |
以上是configure命令的部分参数,其他参数可以使用bash configure --help
命令查询到。
所有参数通过以下形式使用:
bash configure [options]
例如,编译FastDebug版、仅含Server模式的HotSpot虚拟机,命令如下:
bash configure --enable-debug --with-jvm-variants=server
如果在检查配置中缺少依赖,直接按照提示安装即可,可能出现的问题:
- configure: error: Cloud not find fontconfig! You might be able to fix this by running ‘
sudo apt-get install libfontconfig1-dev
’.
配置成功的信息如下:
最后,通过make
命令编译。编译完成如下:
进入OpenJDK源码的“build/配置名称/jdk”目录下,就可以看到完整的编译结果了。目录结构如下:
如果多次编译,或者目录结构成功产生后又再次修改了配置,必须先使用
make clean
和make dist-clean
命令清理目录,才能确保配置生效。
在当前目录下,使用./bin/java -version
进行验证,可以看到是我们编译的OpenJDK 12版本。