Linux | Ubuntu配置JDK源码编译环境
环境说明
- 宿主机环境:Windows 11 家庭版 21H2 版本
- 宿主机操作系统版本:22000.348
- 虚拟机环境:VMware® Workstation 17 Pro
- 虚拟机操作系统版本:Ubuntu 22.10
- 参考:《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》
Win 11 使用 VMware 的问题
在 Win 11 家庭版中使用 VMware 可能会产生一些兼容性问题,比如蓝屏、无法启动镜像等。可解决的方式包括:
- 更换 VMware 至新版本,测试使用 VMware 15、16、17 版本,仅 17 版本不会产生蓝屏现象
- 开启 Hyper-V 功能,在控制面板-程序-启动或关闭 Windows 功能-勾选“虚拟机平台”与“Windows 虚拟机监控程序平台”
- 禁用 Device Guard,Win 11 家庭版无法正常启动
gpedit.msc
,需要在注册表regedit
中找到Device Guard
将其默认值置 0
apt 软件源更新
修改apt软件源,官方源下载速度较慢,切换至国内镜像源提高速度。先将系统软件源文件做个备份,然后用国内镜像源替换文件中内容。vi 使用方法在此不作赘述。
sudo vi /etc/apt/sources.list
可替换的国内镜像源包括阿里开源镜像站、清华大学开源镜像站等。如下是清华大学开源镜像站中 Ubuntu 22.10 的镜像源,其中deb-src
部分是源码镜像。
# Tsinghua
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ kinetic main restricted universe multiverse
deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ kinetic main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ kinetic-updates main restricted universe multiverse
deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ kinetic-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ kinetic-backports main restricted universe multiverse
deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ kinetic-backports main restricted universe multiverse
# 镜像站有同步延迟,安全更新可能不够及时,不建议替换 security 源,使用下述官方源
# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ kinetic-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ kinetic-security main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu/ kinetic-security main restricted universe multiverse
deb-src http://security.ubuntu.com/ubuntu/ kinetic-security main restricted universe multiverse
# 预发布软件源,不建议启用
# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ kinetic-proposed main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ kinetic-proposed main restricted universe multiverse
软件源修改完毕后,更新源文件:
sudo apt update
软件安装的指令如下,XXX是需要安装的软件名,添加可选参数 -y
默认同意安装过程中所有的确认部分:
sudo apt install XXX
软件及依赖库安装
更新完软件源后即可安装需要用到的软件与依赖。
可能会用到的
- net-tools:网络配置工具,可选安装。
- open-vm-tools-desktop:
VMware Tools
,该版本可实现分辨率自动调整,可选安装。 - gedit:Desktop 版本的文本编辑器,可选安装。
- openssh-server:
ssh
服务,可选安装。 - mercurial:检索跳转安装,类似
git
,用于拉取资源等,可选安装。 - git:项目版本控制,用于拉取项目等,需安装。
- dpkg:用于软件版本管理,包含
update-alternatives
等,需安装。
JDK依赖
- openjdk-11-jdk
- build-essential
其他依赖
- libfreetype6-dev
- libcups2-dev
- libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev
- libasound2-dev
- libffi-dev
- autoconf
- libfontconfig1-dev
版本调整
由于下载的安装构建工具版本过高,在后续编译过程中会导致报错,需要安装 GCC-7
的版本,需要经过下述步骤:
# Ubuntu 更新软件源配置文件
sudo vi /etc/apt/sources.list
# 向文件中添加如下软件源
deb [arch=amd64] http://archive.ubuntu.com/ubuntu focal main universe
# 更新源文件
sudo apt update
# 安装 gcc-7 g++-7
sudo apt -y install gcc-7 g++-7
# 多版本控制
# 维护刚安装的 7 与 ubuntu 22.10 默认安装的 12
# 最后的数字越大 优先级越高
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 400
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 300
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 400
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 300
# 可通过如下指令查看当前 gcc 版本管理情况
sudo update-alternatives --config gcc
sudo update-alternatives --display gcc
OpenJDK 12 源码获取
方式一
通过 git
获取
# 切换至合适目录存放代码
# 获取源码
sudo git clone https://github.com/openjdk/jdk.git
# 源码下载后默认文件夹名为 jdk
cd jdk
# 切换分支为 12
sudo git checkout jdk-12-ga
该方式也可直接从宿主机下载相应版本代码,然后通过FTP、共享文件等方式发送文件至虚拟机中。
方式二
OpenJDK 官网直接获取,但从该网站下载不稳定,可能会多次下载失败
# 切换至合适目录存放代码
# 获取源码 需安装 mercurial
sudo hg clone https://hg.openjdk.java.net/jdk/jdk12
源码编译
使用 configure
命令来对编译进行控制,如检查依赖项、参数选择、构建等。在源码中包括对此部分的描述,在文件 jdk/doc/building.md
中包含详细描述。
--enable-debug
- Set the debug level tofastdebug
(this is a shorthand for--with-debug-level=fastdebug
)--with-debug-level=<level>
- Set the debug level, which can berelease
,fastdebug
,slowdebug
oroptimized
. Default isrelease
.optimized
is variant ofrelease
with additional Hotspot debug code.--with-native-debug-symbols=<method>
- Specify if and how native debug symbols should be built. Available methods arenone
,internal
,external
,zipped
. Default behavior depends on platform. See Native Debug Symbols for more details.--with-version-string=<string>
- Specify the version string this build will be identified with.--with-version-<part>=<value>
- A group of options, where<part>
can be any ofpre
,opt
,build
,major
,minor
,security
orpatch
. Use these options to modify just the corresponding part of the version string from the default, or the value provided by--with-version-string
.--with-jvm-variants=<variant>[,<variant>...]
- Build the specified variant (or variants) of Hotspot. Valid variants are:server
,client
,minimal
,core
,zero
,custom
. Note that not all variants are possible to combine in a single build.--with-jvm-features=<feature>[,<feature>...]
- Use the specified JVM features when building Hotspot. The list of features will be enabled on top of the default list. For thecustom
JVM variant, this default list is empty. A complete list of available JVM features can be found usingbash configure --help
.--with-target-bits=<bits>
- Create a target binary suitable for running on a<bits>
platform. Use this to create 32-bit output on a 64-bit build platform, instead of doing a full cross-compile. (This is known as a reduced build.)
在这里我们使用如下指令执行 configure
命令:
bash configure --enable-debug --with-jvm-variants=server --disable-warnings-as-errors
执行成功会有如下输出:
====================================================
A new configuration has been successfully created in
/home/gx/sourcecode/jdk/build/linux-x86_64-server-fastdebug
using configure arguments '--enable-debug --with-jvm-variants=server --disable-warnings-as-errors'.
Configuration summary:
* Debug level: fastdebug
* HS debug level: fastdebug
* JVM variants: server
* JVM features: server: 'aot cds cmsgc compiler1 compiler2 epsilongc g1gc graal jfr jni-check jvmci jvmti management nmt parallelgc serialgc services shenandoahgc vm-structs zgc'
* OpenJDK target: OS: linux, CPU architecture: x86, address length: 64
* Version string: 12-internal+0-adhoc.gx.jdk (12-internal)
上述输出结果如果有 error 或 warning,不要忽视,检查是否有版本不匹配等问题,这可能会导致 make 失败。
configure
命令执行完毕,可以进行编译。但在此之前,由于 OpenJDK 12 的源码部分对 make 指令兼容性有问题。需要先调整,否则会导致编译失败。这一问题在 OpenJDK 后续版本中有修复。
在 jdk 路径下执行如下指令,修改配置内容:
sudo vi /make/common/MakeBase.gmk
大概在900多行的位置处有如下代码:
# Does the actual work with parameters stripped.
# If the file exists AND the contents is the same as the variable, do nothing
# else print a new file.
# Always returns the name of the file where the value was printed.
# Param 1 - Name of variable
# Param 2 - (optional) name of file to store value in
DependOnVariableHelper = \
$(strip \
$(eval -include $(call DependOnVariableFileName, $1, $2)) \
$(if $(call equals, $(strip $($1)), $(strip $($1_old))),,\
$(call MakeDir, $(dir $(call DependOnVariableFileName, $1, $2))) \
$(if $(findstring $(LOG_LEVEL), trace), \
$(info NewVariable $1: >$(strip $($1))<) \
$(info OldVariable $1: >$(strip $($1_old))<)) \
$(call WriteFile, $1_old:=$(call DoubleDollar,$(call EscapeHash,$($1))), \
$(call DependOnVariableFileName, $1, $2))) \
$(call DependOnVariableFileName, $1, $2) \
)
将其修改为如下代码并保存:
DependOnVariableHelper = \
$(strip \
$(eval $1_filename := $(call DependOnVariableFileName, $1, $2)) \
$(if $(wildcard $($1_filename)), $(eval include $($1_filename))) \
$(if $(call equals, $(strip $($1)), $(strip $($1_old))),,\
$(call MakeDir, $(dir $($1_filename))) \
$(if $(findstring $(LOG_LEVEL), trace), \
$(info NewVariable $1: >$(strip $($1))<) \
$(info OldVariable $1: >$(strip $($1_old))<)) \
$(call WriteFile, $1_old:=$(call DoubleDollar,$(call EscapeHash,$($1))), \
$($1_filename))) \
$($1_filename) \
)
修改完成后,便可以进行编译了:
make images
编译完成后,通过如下指令验证JDK版本:
./build/linux-x86_64-server-fastdebug/jdk/bin/java --version
如果是如下结果则表明编译成功:
openjdk 12-internal 2019-03-19
OpenJDK Runtime Environment (fastdebug build 12-internal+0-adhoc.gx.jdk)
OpenJDK 64-Bit Server VM (fastdebug build 12-internal+0-adhoc.gx.jdk, mixed mode)
如果多次编译,在每次编译前要清除之前的编译记录,使用如下指令:
make clean && make dist-clean