JVM-Ubuntu18.04.1下编译OpenJDK8
近期开始学习JVM,看的是周老师的《深入理解Java虚拟机》,打算先自己编译个JDK来提升对JVM的兴趣。本文分三部分来描述编译OpenJDK的过程,分别是编译前准备工作、构建编译环境、进行编译,在这三部分内容中顺带把趟的坑一起说明下。
一、编译前准备工作
1.1 安装Linux环境
编译OpenJDK,Windows环境要比Linux环境复杂,故选择安装Linux环境。可以自己在Windows下安装虚拟机,也可以直接安装双系统,专门空出一个磁盘来安装Linux,我选择了后者,安装最新版的Ubuntu 18.04.1 LTS,搭建双系统的过程这里不再赘述,网络上有非常多的材料可以参考。我的电脑是ThinkPad-E480,安装完成后巨坑,无法连接WIFI,害得我花了一个晚上来解决这个问题,附上解决问题链接:
https://askubuntu.com/questions/1070593/lenovo-thinkpad-e480-no-wifi-adaptor-found-in-ubuntu-18-04
1.2 下载OpenJDK源码
原本是计划按照周老师的书一步一步的操作,所以计划的是编译OpenJDK7,OpenJDK7对应的BootStrapJDK是OpenJDK6,无奈OpenJDK6在Ubuntu 18.04.1 LTS上很难再找到资源,故放弃了这个思路,改成编译OpenJDK8,BootStrapJDK是OpenJDK7,实践证明这个操作也是一路的坑,后面环节再叙述。
确定了思路后,接下来就是下载OpenJDK8的源代码,有两种方式:
第一种就是Mercurial,优点就是操作起来很简单,不需要再解压文件包,缺点就是需要耗费的时间长一些,实际上本人最终就是使用的这种方式,预计耗时半小时左右。Mercurial也是一种版本管理工具,大家可以想象下SVN、Git之类的工具。下载代码的命令如下:
hg clone http://hg.openjdk.java.net/jdk8u/jdk8u-dev
cd jdk8u-dev
sh get_source.sh
第二种就是手动方式,说白了就是自己去下载源码包,然后解压,优点就是耗时短,但相对来说如果不会查找资源,就只能下载到老版本的源代码,比如我就只找到这个链接http://jdk.java.net/java-se-ri/8下的源代码,这个版本是2015年的版本,距离现在已经过去了三年,这样的代码其实在后面的编译过程中如果遇到一些问题就无法判断是Linux的问题还是OpenJDK8的代码问题。
到目前为止,已经有了Linux操作系统,需要编译的OpenJDK源代码也已经有了,下一个环节便是思考如何构建编译环境。
二、构建编译环境
学习了这么多年,大家应该都具备了一定的学习方法。做IT的一个很重要的学习方法就是在拿到资料后,最好先翻阅下这个资料的DEMO或者是README之类的。同样,OpenJDK源代码目录下也有这样一个文件,叫做README-builds.html。
这个文件基本上贯穿了咱们本文的操作流程,首先来看下Introduction:
The
build is now a "configure &&" style build
makeAny
GNU make 3.81 or newer should workThe
build should scale, i.e. more processors should cause the build to
be done in less wall-clock timeNested
or recursive make invocations have been significantly reduced, as
has the total fork/exec or spawning of sub processes during the
buildWindows
MKS usage is no longer supportedWindows
Visual Studiovsvars*.batand
vcvars*.batfiles are run automaticallyAnt
is no longer used when building the OpenJDKUse
of ALT_* environment variables for configuring the build is no
longer supported
和OpenJDK7的构建相比,已经不再需要Ant,另外ALT_*
的环境变量也不再支持,OpenJDK7的编译过程可查看周老师的书,也可以网上查阅其他资料。
文件的第二部分内容是下载源代码,目前代码下载环节已在本文1.2中体现,这里不再赘述。
第三部分就是Building,这里声明了各个操作系统环境中的软件硬件要求,明确要求了OpenJDK8的boot
JDK是JDK
7。
2.1
安装boot
JDK
在文件中的Specific
Developer Build Environments部分实际也约定了如何安装boot
JDK,命令如下(在Ubuntu
18.04.1 LTS中aptitude应该改成
apt-get):
sudo aptitude build-dep openjdk-
sudo aptitude install openjdk--jdk
实际执行下来,如上命令也是不成功的,提示没有可安装候选,这个也就是本文1.2提到的其中一个坑,该如何解决呢?请看https://askubuntu.com/questions/761127/how-do-i-install-openjdk-7-on-ubuntu-16-04-or-higher,里面的ppa方式也已经过期了,只能按MDMower描述的方案来操作,我这边选择了Manual Installation,最终成功安装boot JDK,结果如下:
lingjiango@lingjiango-ThinkPad-E480:~$ java -version
java version "1.7.0_161"
OpenJDK Runtime Environment (IcedTea 2.6.) (7u161-2.6.-)
OpenJDK -Bit Server VM (build 24.161-b01, mixed mode)
2.2 依赖检查
实际上如果是按照README-builds.html的流程,在安装boot JDK之前是先进行依赖检查的,即使没有先安装boot JDK,直接通过bash ./configure来检查的话,这步最先提示的也是安装boot JDK,提示如下:
configure: Could not find a valid Boot JDK. You might be able to fix this by running 'sudo apt-get install openjdk-7-jdk'.
configure: This might be fixed by explicitely setting –with-boot-jdk
在完成本文2.1后,接下来就是递归执行bash ./configure来检查编译环境的依赖项是否全部安装完成。直到看到这个结果:
====================================================
A new configuration has been successfully created in
/home/lingjiango/jdk8u-dev/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: Tools summary:
* Boot JDK: java version "1.7.0_161" OpenJDK Runtime Environment (IcedTea 2.6.) (7u161-2.6.-) OpenJDK -Bit Server VM (build 24.161-b01, mixed mode) (at /usr/lib/jvm/java--openjdk-amd64)
* Toolchain: gcc (GNU Compiler Collection)
* C Compiler: Version 7.3. (at /usr/bin/gcc)
* C++ Compiler: Version 7.3. (at /usr/bin/g++) Build performance summary:
* Cores to use:
* Memory limit: MB
这里再补充说明下,在递归执行依赖检查的过程中可能会提示这个 libx11-dev,Ubuntu 18.04.1 LTS是这么提示安装项目的:
sudo apt-get install libX11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev
libX11-dev的X是大写的,应该会提示找不到这个依赖项,这个时候要把大写X改成小写的x,为 libx11-dev,就可以找到依赖项了。
到这一步,OpenJDK8的编译环境就已经准备好了,下一步就是编译OpenJDK8。
三、进行编译
编译的代码很简单,直接make
all即可,当然也可以按照README-builds.html中对make执行带参数编译,说明如下:
|
Make |
Description |
|---|---|
|
empty |
build |
|
|
build |
|
|
build |
|
|
create |
|
|
install |
|
|
remove |
|
|
remove |
|
|
give |
在编译前还有几个注意事项,这些注意事项在文件README-builds.html中也是有体现的:
设定语言选项,可先执行echo $LANG,看下输出,如果不是C,则执行export LANG=C;
设定PATH,可先执行echo $PATH,看下输出,如果没有boot JDK,则执行export PATH="/usr/lib/jvm/java-7-openjdk-amd64/bin:${PATH}";
检查JAVA_HOME ,可先执行echo $JAVA_HOME,看下输出,如果有值则需要unset JAVA_HOME;
这三步检查执行通过后,就可以执行make命令了。一切顺利的话,就可以看到这样的编译结果:
## Finished docs (build time ::) ----- Build times -------
Start -- ::
End -- ::
:: corba
:: demos
:: docs
:: hotspot
:: images
:: jaxp
:: jaxws
:: jdk
:: langtools
:: nashorn
:: TOTAL
-------------------------
Finished building OpenJDK for target 'all'
看到这样的结果,表示编译成功,可以到多个目录下的bin目录执行./java -version来验证。
lingjiango@lingjiango-ThinkPad-E480:~/jdk8u-dev/build/linux-x86_64-normal-server-release/jdk/bin$ ./java -version
openjdk version "1.8.0-internal"
OpenJDK Runtime Environment (build 1.8.-internal-lingjiango_2018_09_23_16_59-b00)
OpenJDK -Bit Server VM (build 25.71-b00, mixed mode) lingjiango@lingjiango-ThinkPad-E480:~/jdk8u-dev/build/linux-x86_64-normal-server-release/images/j2sdk-image/bin$ ./java -version
openjdk version "1.8.0-internal"
OpenJDK Runtime Environment (build 1.8.-internal-lingjiango_2018_09_23_16_59-b00)
OpenJDK -Bit Server VM (build 25.71-b00, mixed mode)
事实上,我在编译的过程中就不顺利,主要遇到了两个问题:
1、编译内核版本问题
在本文1.2中已经提到了两种获取源码的方式,其实一开始我采用的是方法二,下载的是2015年的openjdk-8u40,这个源码包中的/hotspot/make/linux/Makefile文件中声明的SUPPORTED_OS_VERSION不支持4.X的内核,所以编译报如下截图的错误:

因为Ubuntu 18.04.1 LTS的内核是4.15.0-34-generic,故如果要继续编译下去,需要将Makefile的SUPPORTED_OS_VERSION那行后面添加4%。
2、-Werror=deprecated-declarations问题
在我把问题1解决后,继续编译,后面又碰到了很多神奇的问题,而且很难查找到相关解决问题的资料。所以我只能从逻辑上推理下,OpenJDK8一直在更新发展,Ubuntu 也一直在更新发展,两者同步更新,应该取最新的文件编译起来问题才会少一些,而且猜测也有更多的资料可查,但是现在用的是2015年的openjdk-8u40,而 Ubuntu又是最新的,所以有问题估计也没有人去修复(其实我们的很多应用系统一样也是这个道理,年久失修,没什么人用的功能有问题也不一定去修复)。这个时候我果断切换到最新的OpenJDK8,通过Mercurial下载最新的代码,然后在Ubuntu 18.04.1 LTS编译。编译的过程就碰到一个问题,报错如下:
os_linux.inline.hpp::: error: 'int readdir_r(DIR*, dirent*, dirent**)' is deprecated [-Werror=deprecated-declarations]
查阅网上资料说是这是因为glibc >= 2.24的情况下,方法 readdir_r被 deprecated,不支持了,通过getconf GNU_LIBC_VERSION检查发现Ubuntu 18.04.1 LTS版本为glibc 2.27,而且也有很多人在OpenJDK上报了BUG,链接https://bugs.openjdk.java.net/browse/JDK-8179887,6/7/8/9都不打算修复此问题,会在11修复这个BUG,所以当前只能通过其他的方式来解决,解决方案如下:
在./hotspot/make/linux/makefiles/gcc.make文件中找到WARNINGS_ARE_ERRORS = -Werro,注释该段或改成WARNINGS_ARE_ERRORS = -Wno-all。再编译就会忽略掉警告,直到编译完成。
参考资料:
《深入理解Java虚拟机》
README-builds.html
JVM-Ubuntu18.04.1下编译OpenJDK8的更多相关文章
- ubuntu18.04.2下编译openjdk9源码
最近在看<深入理解Java虚拟机 第二版>这本书,上面有关于自己编译OpenJDK源码的内容.自己根据书里的指示去操作,花了三天的时间,重装了好几次Ubuntu(还不知道快照这个功能,好傻 ...
- ubuntu-12.04.5下编译openjdk8
bash ./configure --with-target-bits=64 --with-boot-jdk=/usr/java/jdk1.7.0_80/ --with-debug-level=slo ...
- Ubuntu18.04环境下melodic安装gmapping
Ubuntu18.04 环境下melodic中很多包没有提供sudo apt install的安装方式,需要通过源代码安装,安装方法如下: 1.先安装依赖库: sudo apt--dev sudo a ...
- Ubuntu13.04 Eclipse下编译安装Hadoop插件及使用小例
Ubuntu13.04 Eclipse下编译安装Hadoop插件及使用小例 一.在Eclipse下编译安装Hadoop插件 Hadoop的Eclipse插件现在已经没有二进制版直接提供,只能自己编译. ...
- ubuntu18.04.2LTS下如何用五笔输入法 --Linux
ubuntu18.04.2LTS下自带五笔输入法,不用去单独下载 1.在设置中找到区域和语言 2.点击加号添加输入源 3.选择,选择「汉语」 4.选择「极点五笔」 开始你的五笔输入法之旅…… 友情链接 ...
- ubuntu18.04系统下用devstack安装openstack(最新版)
ubuntu18.04系统下用devstack安装openstack(最新版) 2018年12月14日 16:34:14 Cherls 阅读数:427 前期准备: 安装git,升级pip,其他 s ...
- Centos7 下编译 Openjdk8
本文主要介绍如何在 Centos7 下编译 Openjdk8 源码,<深入理解java虚拟机>第二版网上好多 openjdk7 的帖子,编译 jdk8 和 7 还是有些差别的,比如大家经常 ...
- 在Ubuntu 16.04 LTS下编译安装OpenCV 4.1.1
目录 一 安装前的准备 二 编译并安装OpenCV 4.1.1 注:原创不易,转载请务必注明原作者和出处,感谢支持! OpenCV目前(2019-8-1)的最新版本为4.1.1.本文将介绍如何在Ubu ...
- Win10下编译OpenJDK8
导航目录 Win10下编译OpenJDK8 相关参考文章 编译环境 编译前准备 1.安装 Visual Studio 2010 Professional 2. 准备OpenJDK8 3. 编译JDK环 ...
随机推荐
- Android 代码混淆配置总结
一.前言 为何需要混淆呢?简单的说,就是将原本正常的项目文件,对其类,方法,字段,重新命名,a,b,c,d,e,f…之类的字母,达到混淆代码的目的,这样反编译出来,结构乱糟糟的,看了也头大. 另外说明 ...
- 吴恩达机器学习笔记21-正则化线性回归(Regularized Linear Regression)
对于线性回归的求解,我们之前推导了两种学习算法:一种基于梯度下降,一种基于正规方程. 正则化线性回归的代价函数为: 如果我们要使用梯度下降法令这个代价函数最小化,因为我们未对theta0进行正则化,所 ...
- phpspreadsheet导出数据到Excel
之前我们使用PHP导出Excel数据时使用的是PHPExcel库,但是phpoffice已经官方宣布PHPExcel已经被废弃不在维护,推荐使用phpspreadsheet,如下图所示 我们可以通过c ...
- 第一节:学会Java前提-手把手教你配置JDK环境变量
前言 大家好,今天写一遍学会Java前提-手把手教你配置JDK环境变量的概述,希望你们喜欢 下载地址 下载jdk,和eclipse就比较简单了,提供JDK 9 地址: http://www.oracl ...
- Mysql数据库异常
1. Mysql数据库异常 1.1. 数据库问题之Got error 28 from storage engine 原因首先检查磁盘是否已满,df -h一下 很可能是日志数据过大,查看该目录下文件夹和 ...
- vue搭建多页面开发环境
自从习惯开发了单页面应用,对多页面的页面间的相互跳转间没有过渡效果.难维护极度反感.但是最近公司技术老大说,当一个应用越来越大的时候单页面模式应付不来,但是没讲怎么应付不来,所以还得自己去复习一遍这两 ...
- mesos支持gpu代码分析以及capos支持gpu实现
这篇文章涉及mesos如何在原生的mesoscontainerizer和docker containerizer上支持gpu的,以及如果自己实现一个mesos之上的framework capos支持g ...
- leetcode — sqrtx
/** * Source : https://oj.leetcode.com/problems/sqrtx/ * * * Implement int sqrt(int x). * * Compute ...
- [深度学习] 权重初始化--Weight Initialization
深度学习中的weight initialization对模型收敛速度和模型质量有重要影响! 在ReLU activation function中推荐使用Xavier Initialization的变种 ...
- 使用ZeroBrane Studio调试Openresty lua脚本
介绍 ZeroBraneStudio 作为轻量级.跨平台的Lua IDE,已被广泛用来调试各种Lua引擎游戏框架.Openresty.Wireshark脚本等等. Openresty 是一个建立在Ng ...