Ubuntu22环境下编译OpenJDK12源码
0. 使用环境说明:
宿主机操作系统:Windows 10 专业版
虚拟机软件:VMware® Workstation 16 Pro
虚拟机操作系统:ubuntu-22.04.1-desktop-amd64.iso
虚拟机安装步骤本文就不再说明,下面提一下两个可能会使用到的小技巧:
0.1 宿主机和虚拟机相互复制内容
在虚拟机中执行下面一条命令即可
sudo apt-get install open-vm-tools-desktop
0.2 虚拟机的窗口大小调整
一般在刚安装完虚拟机系统之后,窗口可能会比较小,在安装完open-vm-tools-desktop
后,如下图位置会出现**立即适应客户机
**选项,点击它即可使客户机窗口自动适应虚拟机窗口大小。
1. 安装JDK11
注意:
Ubuntu 在安装启动之后,默认是不允许 “su” 到 root用户的,如果你是新装的系统,第一次可能需要先重置root密码,才可以登录。
sudo passwd
Jdk里面的代码很多都是用Java语言写的,所有需要N-1版本的JDK作为运行时环境,本文需要JDK11作为JDK12的运行时环境。
sudo apt-get install openjdk-11-jdk
设置Java环境变量:
sudo vim /etc/profile
把下面内容追加到**/etc/profile
**文件中
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
激活**/etc/profile
**文件
sudo source /etc/profile
2 获取OpenJdk12的源代码
2.1安装git
如果没有安装git,先安装git
sudo apt install git
2.2 拉取openjdk源码
从github上clone下来openjdk源码,如下:
cd /home/gx/sourcecode
git clone https://github.com/openjdk/jdk
cd jdk
git checkout jdk-12-ga
其他获取源码途径:
- openjdk官网:https://hg.openjdk.java.net/jdk/jdk12/,不过这个网站下载时会频繁的中断下载,尝试几次均下载失败。
- github:https://github.com/openjdk/jdk,直接直接对应版本的tag即可
3. 安装依赖类库
3.1 切换到root用户
步骤2.2中安装的第三方类库比较多,所以直接切换到root用户操作的,步骤2.2中不做特别说明的时候,默认都是在root用户下面操作的。
su # 切换root用户
3.2 安装gcc和g++
很多地方都是使用以下方式安装构建工具的,
apt-get install -y build-essential
但是上述命令安装的版本(11+)较新,编译的时候会报错,所以要经过下面的步骤安装7+版本:
# ubuntu软件源配置文件
gedit /etc/apt/sources.list
# 向文件中添加如下代码,追加一个软件源
deb [arch=amd64] http://archive.ubuntu.com/ubuntu focal main universe
# 更新源文件
apt-get update
# 安装 gcc-7 g++-7
apt-get -y install gcc-7 g++-7
# 多版本管理 最后的数字越大,优先级越高 这里维护了7 9 11三个版本 默认是版本7
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 50
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 50
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 10
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 10
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 30
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-11 30
可以查看当前版本列表
update-alternatives --config gcc
有 3 个候选项可用于替换 gcc (提供 /usr/bin/gcc)。
选择 路径 优先级 状态
------------------------------------------------------------
* 0 /usr/bin/gcc-7 50 自动模式
1 /usr/bin/gcc-11 30 手动模式
2 /usr/bin/gcc-7 50 手动模式
3 /usr/bin/gcc-9 10 手动模式
其中自动模式就是默认值
3.3 安装其他依赖
apt-get install -y libfreetype6-dev
apt-get install -y libcups2-dev
apt-get install -y libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev
apt-get install -y libasound2-dev
apt-get install -y libffi-dev
apt-get install -y autoconf
apt-get install -y libfontconfig1-dev
4 编译源代码
安装完所需依赖之后,就可以进行源码编译了。
4.1 执行configure命令
configure命令是用来检查依赖项、参数配置和构建输出目录结构等。
bash configure --enable-debug --with-jvm-variants=server --disable-warnings-as-errors
--enable-debug
- 设置编译级别为fastdebug
(这是--with-debug-level=fastdebug
的简写)--with-debug-level=<level>
- 设置编译级别, 可选值有release
,fastdebug
,slowdebug
,optimized
. 默认值为release
.optimized
是release
的特定模式,包含额外的Hotspot虚拟机调试参数.--with-native-debug-symbols=<method>
- 确定调试符号信息的编译方式.可选值为none
,internal
,external
,zipped
.--with-version-string=<string>
- 设置编译JDK的版本号.--with-version-<part>=<value>
-<part>
的值可以为pre
,opt
,build
,major
,minor
,security
或patch
. 用于修改默认版本号或者通过--with-version-string
设置的版本号的某一部分 .--with-jvm-variants=<variant>[,<variant>...]
- 编译特定模式(V ariants)的HotSpot虚拟机,可以 多个模式并存,可选值为server
,client
,minimal
,core
,zero
,custom
。注意不是所有的模式都可以合并起来使用.--enable-jvm-feature-<feature>
or--disable-jvm-feature-<feature>
- 针对–with-jvm-variants=custom时的自定义虚拟机特 性列表(Features)。激活或禁用HotSpot虚拟机的某个特性(<feature>
). 你也可以同时激活一组特性, 特性之间用空格或者逗号分隔, 比如--with-jvm-features=<feature>[,<feature>...]
. 如果 特性(<feature>
)加上前缀-
, 则代表禁用该特性. 这些选项将改变虚拟机的默认特性. 对于custom
模式, 默认特性列表为空. 使用bash configure --help
可以找到完整的特性列表.--with-target-bits=<bits>
-指明要编译32位还是64位的Java虚拟机,在64位机器上也可以通过交叉 编译生成32位的虚拟机。
/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.--enable-jvm-feature-<feature>
or--disable-jvm-feature-<feature>
- Include (or exclude)<feature>
as a JVM feature in Hotspot. You can also specify a list of features to be enabled, separated by space or comma, as--with-jvm-features=<feature>[,<feature>...]
. If you prefix<feature>
with a-
, it will be disabled. These options will modify the default list of features for the JVM variant(s) you are building. For thecustom
JVM variant, the default list is empty. A complete list of valid 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命令执行成功,会看到类似下面的输出内容:
====================================================
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)
Tools summary:
* Boot JDK: openjdk version "11.0.16" 2022-07-19 OpenJDK Runtime Environment (build 11.0.16+8-post-Ubuntu-0ubuntu122.04) OpenJDK 64-Bit Server VM (build 11.0.16+8-post-Ubuntu-0ubuntu122.04, mixed mode, sharing) (at /usr/lib/jvm/java-11-openjdk-amd64)
* Toolchain: gcc (GNU Compiler Collection)
* C Compiler: Version 7.5.0 (at /usr/bin/gcc)
* C++ Compiler: Version 7.5.0 (at /usr/bin/g++)
Build performance summary:
* Cores to use: 2
* Memory limit: 3889 MB
如果多次编译,在每次编译前,需要清除之前的编译记录:
make clean && make dist-clean
4.2 执行make命令
输入以下命令开始整个openjdk的编译:
make images
编译成功的结果:
Creating support/modules_cmds/jdk.jstatd/jstatd from 1 file(s)
Creating support/modules_libs/jdk.management/libmanagement_ext.so from 8 file(s)
Creating support/modules_libs/jdk.management.agent/libmanagement_agent.so from 1 file(s)
Creating support/modules_libs/jdk.net/libextnet.so from 1 file(s)
Creating support/modules_libs/jdk.pack/libunpack.so from 7 file(s)
Creating support/modules_cmds/jdk.pack/pack200 from 1 file(s)
Creating support/modules_cmds/jdk.pack/unpack200 from 7 file(s)
Creating support/modules_cmds/jdk.rmic/rmic from 1 file(s)
Creating support/modules_cmds/jdk.scripting.nashorn.shell/jjs from 1 file(s)
Creating support/modules_libs/jdk.sctp/libsctp.so from 3 file(s)
Creating support/modules_libs/jdk.security.auth/libjaas.so from 1 file(s)
Compiling 4 files for BUILD_JIGSAW_TOOLS
Stopping sjavac server
Finished building target 'default (exploded-image)' in configuration 'linux-x86_64-server-fastdebug'
4.3 验证编译结果
通过查看编译后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)
5. 常见问题
JDK源码的编译过程还是十分复杂的,任何一个环节出现问题都有可能导致最终编译失败。
不光个人操作和环境问题会导致最终编译失败,就连openJdk源码本身也有可能会有问题,所以给整个编译过程带来了巨大的困难!
5.1 gcc 版本问题
在执行configure命令的时候,如果出现以下的警告信息,不要忽略掉,因为不解决这些警告,最后的编译(执行make的时候)会失败的。
The following warnings were produced. Repeated here for convenience:
WARNING: C and C++ compiler have different version numbers, gcc (Ubuntu 11.2.0-19ubuntu1) 11.2.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. vs g++ (Ubuntu 11.2.0-19ubuntu1) 11.2.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE..
WARNING: This typically indicates a broken setup, and is not supported
WARNING: You are using gcc older than 4.8. This is not a supported configuration.
WARNING: C and C++ compiler have different version numbers, gcc (Ubuntu 11.2.0-19ubuntu1) 11.2.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. vs g++ (Ubuntu 11.2.0-19ubuntu1) 11.2.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE..
WARNING: This typically indicates a broken setup, and is not supported
5.1.1 原因
因为gcc版本过高导致,切换到gcc-7就可以解决警告问题。
5.1.2 解决办法
安装gcc-7、g+±7 ,本文一开始就安装了gcc-7、g+±7,就是为了避免出现该问题。
5.2 make 命令版本问题
在执行make命令的时候如果出现下面的错误,很可能就是jdk源码自身的问题。
Building target 'images' in configuration 'linux-x86_64-server-fastdebug'
gmake[3]: *** 没有规则可制作目标“/home/gx/sourcecode/jdk/build/linux-x86_64-server-fastdebug/buildtools/langtools_tools_classes/_the.BUILD_TOOLS_LANGTOOLS.vardeps”,由“/home/gx/sourcecode/jdk/build/linux-x86_64-server-fastdebug/buildtools/langtools_tools_classes/_the.BUILD_TOOLS_LANGTOOLS_batch” 需求。 停止。
gmake[3]: *** 正在等待未完成的任务....
gmake[2]: *** [make/Main.gmk:73:buildtools-langtools] 错误 2
gmake[2]: *** 正在等待未完成的任务....
gmake[3]: *** 没有规则可制作目标“/home/gx/sourcecode/jdk/build/linux-x86_64-server-fastdebug/make-support/vardeps/make/ModuleWrapper.gmk/java.base/ORDERED_CFG_VARIANTS.vardeps”,由“/home/gx/sourcecode/jdk/build/linux-x86_64-server-fastdebug/support/modules_libs/java.base/jvm.cfg” 需求。 停止。
gmake[3]: *** 正在等待未完成的任务....
gmake[2]: *** [make/Main.gmk:162:java.base-copy] 错误 2
ERROR: Build failed for target 'images' in configuration 'linux-x86_64-server-fastdebug' (exit code 2)
No indication of failed target found.
Hint: Try searching the build log for '] Error'.
Hint: See doc/building.html#troubleshooting for assistance.
make[1]: *** [/home/gx/sourcecode/jdk/make/Init.gmk:310:main] 错误 2
make: *** [/home/gx/sourcecode/jdk/make/Init.gmk:186:images] 错误 2
5.2.1 原因
这个问题是jdk源码对make4.3版本的兼容性问题
这个问题在jdk15修复了:8237879: make 4.3 breaks build
原文地址:https://github.com/openjdk/panama-foreign/commit/af5c725b
5.2.2 解决办法
修改make/common/MakeBase.gmk的代码
修改之前:
# 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) \
)
修改之后:
# 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 $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) \
)