编译JDK步骤大致是这样的:
看起来很简单,但是实践的时候总会遇到很多问题。所以我总结了一下自己的踩坑经历。
安装Mercurial
sudo apt-get install mercurial
访问OpenJDK的Mercurial仓库:
https://hg.openjdk.java.net/jdk8u/jdk8u/
点击左边browser
,再点击左边zip
,下载回来解压,打开看README-builds.html
,有如下说明:
Getting the Source
To get the entire set of OpenJDK Mercurial repositories use the script get_source.sh located in the root repository:
hg clone http://hg.openjdk.java.net/jdk8/jdk8 YourOpenJDK cd YourOpenJDK bash ./get_source.shOnce you have all the repositories, keep in mind that each repository is its own independent repository.
You can also re-run
./get_source.sh
anytime to pull over all the latest changesets in all the repositories.This set of nested repositories has been given the term "forest" and there are various ways to apply the same hg command to each of the repositories.
For example, the script
make/scripts/hgforest.sh
can be used to repeat the same hg command on every repository, e.g.cd YourOpenJDK bash ./make/scripts/hgforest.sh status
刚才下载zip包其实是相当于 hg clone
的步骤,但是如果单纯下载zip包解压,运行./get_source.sh
脚本,会报错:
ERROR: Need initial repository to use this script
上面报错意思就是,必须要用hg clone
初始化仓库后,才能使用get_source.sh
命令。因此必须要按照上面说明,使用hg clone
命令来初始化jdk的源码仓库:
$ hg clone https://hg.openjdk.java.net/jdk8u/jdk8u/ $ cd jdk8u $ bash ./get_source.sh # Repositories: corba jaxp jaxws langtools jdk hotspot nashorn ............
上面过程结束后,会下载几个模块对应的仓库源码:
Repository | Contains |
---|---|
. (root) | common configure and makefile logic |
hotspot | source code and make files for building the OpenJDK Hotspot Virtual Machine |
langtools | source code for the OpenJDK javac and language tools |
jdk | source code and make files for building the OpenJDK runtime libraries and misc files |
jaxp | source code for the OpenJDK JAXP functionality |
jaxws | source code for the OpenJDK JAX-WS functionality |
corba | source code for the OpenJDK Corba functionality |
nashorn | source code for the OpenJDK JavaScript implementation |
其中就有 jvm的源码 和 jdk的源码
但是通过get_source.sh
脚本下载源码很慢,并不推荐。
按下面顺序找到下载链接:
访问:http://openjdk.java.net/
点击左边 JDK 8
点击文中链接 Linux Distributions
在标题“RI Source Code”标题下找到 zip file
下载:
wget https://download.java.net/openjdk/jdk8u41/ri/openjdk-8u41-src-b04-14_jan_2020.zip $ unzip openjdk-8u41-src-b04-14_jan_2020.zip # 目录改一下名称 $ mv openjdk openjdk-8u41-src
最后我是用打包下载方式下载到open jdk8 的源码的,下面讲解设定源码解压后目录在这里:
$ pwd /home/caibh/source/openjdk-8u41-src $ ls ASSEMBLY_EXCEPTION configure get_source.sh jaxp jdk LICENSE Makefile README test common corba hotspot jaxws langtools make nashorn README-builds.html THIRD_PARTY_README
按README-builds.html
说明,运行bash ./configure
,遇到报错:
configure: error: Could not find all X11 headers (shape.h Xrender.h XTest.h Intrinsic.h). You might be able to fix this by running 'sudo apt-get install libX11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev'. configure exiting with result code 1
按提示安装对应的软件,又报错:
$ sudo apt-get install libX11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev E: 无法定位软件包 libX11-dev
把libX11-dev
中的X
改成小写就可以了:libx11-dev
。
$ sudo apt-get install libx11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev
然后继续运行bash ./configure
,遇到报错:
configure: error: Could not find cups! You might be able to fix this by running 'sudo apt-get install libcups2-dev'. configure exiting with result code 1
按提示安装:
$ sudo apt-get install libcups2-dev
继续运行bash ./configure
,终于没报错:
==================================================== A new configuration has been successfully created in /home/caibh/source/jdk8u/build/linux-x86_64-normal-server-release using default settings. Configuration summary: * Debug level: release * JDK variant: normal * JVM variants: server * OpenJDK target: OS: linux, CPU architecture: x86, address length: 64 Tools summary: * Boot JDK: java version "1.8.0_261" Java(TM) SE Runtime Environment (build 1.8.0_261-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, mixed mode) (at /home/caibh/app/jdk/8u261) * Toolchain: gcc (GNU Compiler Collection) * C Compiler: Version 8.3.0 (at /usr/bin/gcc) * C++ Compiler: Version 8.3.0 (at /usr/bin/g++) Build performance summary: * Cores to use: 10 * Memory limit: 15437 MB
但是上面明显就不对,Boot JDK显示用的是1.8.0_261
,编译JDK8应该用JDK7作为Boot JDK,所以还要配置。
通过查看帮助,能看到很多有用的配置:
$ cd ~/source/jdk8u $ bash ./configure --help
其中就有一条可以配置 Boot JDK:
--with-boot-jdk path to Boot JDK (used to bootstrap build) [probed]
下面先按README-builds.html
文档说明,下载好Boot JDK,以及安装好其他依赖软件,再做一次bash ./configure
按下面顺序找到下载链接:
访问:http://openjdk.java.net/
点击左边 JDK 7
点击文中链接 Linux Distributions
在标题为“JDK 9 & Later”的段落开头找到链接jdk.java.net,选择 7
选中“Accept License Agreement”,然后下载 Linux x64 Binary
下载:
$ cd source $ wget https://download.java.net/openjdk/jdk7u75/ri/jdk_ri-7u75-b13-linux-x64-18_dec_2014.tar.gz # 解压,改下名字 $ mv jdk_ri-7u75-b13-linux-x64-18_dec_2014.tar.gz openjdk-7u75-bin.tar.gz $ tar -xzf jdk7u75.tar.gz $ mv java-se-7u75-ri/ openjdk-7u75-bin
其实README-builds.html
中还提及要安装一些依赖,安装后再执行bash ./configure
,报错应该会少很多:
bash ./configure --with-boot-jdk=/home/caibh/source/openjdk-7u75-bin
执行bash ./configure
后会提示安装ccache,于是我又安装了一下。
$ sudo apt-get install ccache
$ make
报错:
*** This OS is not supported: Linux book 5.10.18-amd64-desktop #1 SMP Mon Mar 1 17:09:41 CST 2021 x86_64 GNU/Linux make[5]: *** [/home/caibh/source/openjdk-8u41-src/hotspot/make/linux/Makefile:238:check_os_version] 错误 1 make[4]: *** [/home/caibh/source/openjdk-8u41-src/hotspot/make/linux/Makefile:259:linux_amd64_compiler2/debug] 错误 2 make[3]: *** [Makefile:231:generic_build2] 错误 2 make[2]: *** [Makefile:177:product] 错误 2 make[1]: *** [HotspotWrapper.gmk:45:/home/caibh/source/openjdk-8u41-src/build/linux-x86_64-normal-server-release/hotspot/_hotspot.timestamp] 错误 2 make: *** [/home/caibh/source/openjdk-8u41-src//make/Main.gmk:109:hotspot-only] 错误 2
报错信息显示check_os_version
的地方出错了,于是找到报错文件所在行:
/home/caibh/source/openjdk-8u41-src/hotspot/make/linux/Makefile:238
# We do not want people accidentally building on old systems (e.g. Linux 2.2.x, # Solaris 2.5.1, 2.6). # Disable this check by setting DISABLE_HOTSPOT_OS_VERSION_CHECK=ok. SUPPORTED_OS_VERSION = 2.4% 2.5% 2.6% 3% 5% // 加入5% OS_VERSION := $(shell uname -r) EMPTY_IF_NOT_SUPPORTED = $(filter $(SUPPORTED_OS_VERSION),$(OS_VERSION)) check_os_version: ifeq ($(DISABLE_HOTSPOT_OS_VERSION_CHECK)$(EMPTY_IF_NOT_SUPPORTED),) $(QUIETLY) >&2 echo "*** This OS is not supported:" `uname -a`; exit 1; // 238行 endif
修改上面代码,加入5.x内核支持,因为我自己的Linux系统,用的就是5.x的内核。
继续执行make
,继续出错,错误的信息很多提示是语法错误,例如:
warning: invalid suffix on literal; C++11 requires a space between literal and string macro ...... warning: ‘int readdir_r(DIR*, dirent*, dirent**)’ is deprecated [-Wdeprecated-declarations] ...... make[6]: *** [/home/caibh/source/openjdk-8u41-src/hotspot/make/linux/makefiles/vm.make:304:precompiled.hpp.gch] 错误 1 make[5]: *** [/home/caibh/source/openjdk-8u41-src/hotspot/make/linux/makefiles/top.make:119:the_vm] 错误 2 make[4]: *** [/home/caibh/source/openjdk-8u41-src/hotspot/make/linux/Makefile:293:product] 错误 2 make[3]: *** [Makefile:231:generic_build2] 错误 2 make[2]: *** [Makefile:177:product] 错误 2 make[1]: *** [HotspotWrapper.gmk:45:/home/caibh/source/openjdk-8u41-src/build/linux-x86_64-normal-server-release/hotspot/_hotspot.timestamp] 错误 2 make: *** [/home/caibh/source/openjdk-8u41-src//make/Main.gmk:109:hotspot-only] 错误 2
经过一番查找资料,判定应该是gcc版本太高导致的,README-builds.html
中也提过C/C++的编译器要求版本是 gcc 4.3 以上,而现在我系统的gcc/g++编译器是8.3,太新了,呵呵。
问题又来了,Deepin的源中没有更低版本的gcc和g++,不想通过编译源码方式安装gcc和g++,想通过apt方式安装。办法是将系统源临时改成Ubuntu 18或16的。经测试Ubuntu 18能安装gcc-5,Ubuntu 16能安装 gcc-4.8。
将源换成Ubuntu 18的:
$ cd /etc/apt $ sudo cp sources.list sources.list.bak $ sudo vim sources.list
替换成下面内容:
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
然后安装证书,更新:
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 3B4FE6ACC0B21F32 $ sudo apt update
最后安装gcc-5
$ sudo apt-get install gcc-5 g++
配置多个gcc
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 100 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 100
切换gcc版本:
sudo update-alternatives --config gcc
配置多个g++
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 100 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-8 100
切换g++版本:
sudo update-alternatives --config g++
编译设置默认会将警告当成错误,造成make的时候会中断,于是需要dirty hack一下。
找到hotspot/make/linux/makefiles/gcc.make
文件,将WARNINGS_ARE_ERRORS
注释掉:
#WARNINGS_ARE_ERRORS = -Werror