以下介绍在Ubuntu 18.04.1系统中源代码编译安装OpenJDK 8,过程分为三段,即编译前准备工作、构建编译环境、进行编译OpenJDK 8,同时也讲解在这三段过程中所出现问题的解决方法。
一、编译OpenJDK 8前准备工作 1.安装Linux环境 编译OpenJDK,Windows环境要比Linux环境复杂,所以选择安装Linux环境。可以自己在Windows下安装虚拟机,也可以直接安装双系统,专门空出一个磁盘来安装Linux,我选择了后者,安装最新版的Ubuntu 18.04.1 LTS,搭建双系统的过程可以参考Win10使用VMware14安装ubuntu-18.04.1-desktop-amd64.iso系统一文。 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 第二种就是手动方式,说白了就是自己去下载源码包,然后解压,优点就是耗时短,但相对来说如果不会查找资源,就只能下载到老版本的源代码,比如我就只找到这个链接下的源代码,这个版本是2015年的版本,距离现在已经过去了三年,这样的代码其实在后面的编译过程中如果遇到一些问题就无法判断是Linux的问题还是OpenJDK8的代码问题。 到目前为止,已经有了Linux操作系统,需要编译的OpenJDK源代码也已经有了,下一个步骤便是思考如何构建编译环境。
二、构建OpenJDK 8编译环境 学习了这么多年,大家应该都具备了一定的学习方法。做IT的一个很重要的学习方法就是在拿到资料后,最好先翻阅下这个资料的DEMO或者是README之类的。同样,OpenJDK源代码目录下也有这样一个文件,叫做README-builds.html。 这个文件基本上贯穿了咱们本文的操作流程,首先来看下Introduction: The build is now a "configure && make" style build Any GNU make 3.81 or newer should work The build should scale, i.e. more processors should cause the build to be done in less wall-clock time Nested or recursive make invocations have been significantly reduced, as has the total fork/exec or spawning of sub processes during the build Windows MKS usage is no longer supported Windows Visual Studio vsvars*.bat and vcvars*.bat files are run automatically Ant is no longer used when building the OpenJDK Use of ALT_* environment variables for configuring the build is no longer supported 和OpenJDK7的构建相比,已经不再需要Ant,另外ALT_* 的环境变量也不再支持,OpenJDK7的编译过程可查看周老师的书。 文件的第二部分内容是下载源代码,目前代码下载环节已在本文(下载OpenJDK源码)中体现,这里不再赘述。 第三部分就是Building,这里声明了各个操作系统环境中的软件硬件要求,明确要求了OpenJDK8的boot JDK是JDK 7。 1.安装boot JDK 在文件中的Specific Developer Build Environments部分实际也约定了如何安装boot JDK,命令如下(在Ubuntu 18.04.1 LTS中aptitude 应该改成apt-get): sudo aptitude build-dep openjdk-7 sudo aptitude install openjdk-7-jdk 实际执行下来,如上命令也是不成功的,提示没有可安装候选,这个也就是本文下载OpenJDK源码提到的其中一个问题,该如何解决呢?我这边参考了: 1].Download the packages intended for your architecture: 以下这些软件包请到:https://ywnz.com/linuxjc/2734.html 下载。 openjdk-7-jdk openjdk-7-jre openjdk-7-jre-headless libjpeg62-turbo libfontconfig1 fontconfig-config 2].(Attempt to) install the packages using dpkg: Ubuntu 17.10 and earlier: sudo dpkg -i openjdk-7-* libjpeg62-turbo* libfontconfig1* fontconfig-config* Ubuntu 18.04 and later: sudo dpkg -i openjdk-7-* libjpeg62-turbo* 3].Check the output from dpkg. If there were dependency problems – which is likely – you will see the following (with your architecture substituted for amd64): Errors were encountered while processing: openjdk-7-jre:amd64 openjdk-7-jre-headless:amd64 openjdk-7-jdk:amd64 If there were no dependency issues, great, you're done, skip to #4. Otherwise, if you need to resolve some dependency issues, this is handled with: sudo apt install -f Notice, there is no need to re-run dpkg after letting apt resolve dependencies. It will automatically finish installation of the openjdk packages. 4].Update java alternatives. You can view all installed java versions with update-java-alternatives --list. To activate OpenJDK Java 1.7, run: sudo update-java-alternatives -s java-1.7.0-openjdk-amd64 You may notice an error about the IcedTeaPlugin.so plugin being unavailable. This isn't a real concern for developers working with the JDK. 最终成功安装boot JDK,结果如下: linux@linux:~$ java -version java version "1.7.0_161" OpenJDK Runtime Environment (IcedTea 2.6.12) (7u161-2.6.12-1) OpenJDK 64-Bit Server VM (build 24.161-b01, mixed mode) 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 在完成本文安装boot JDK后,接下来就是递归执行bash ./configure来检查编译环境的依赖项是否全部安装完成。直到看到这个结果: A new configuration has been successfully created in /home/linux/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: 64 Tools summary: * Boot JDK: java version "1.7.0_161" OpenJDK Runtime Environment (IcedTea 2.6.12) (7u161-2.6.12-1) OpenJDK 64-Bit Server VM (build 24.161-b01, mixed mode) (at /usr/lib/jvm/java-7-openjdk-amd64) * Toolchain: gcc (GNU Compiler Collection) * C Compiler: Version 7.3.0 (at /usr/bin/gcc) * C++ Compiler: Version 7.3.0 (at /usr/bin/g++) Build performance summary: * Cores to use: 7 * Memory limit: 7872 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,就可以找到依赖项了。 到这一步,OpenJDK 8的编译环境就已经准备好了,下一步就是编译OpenJDK 8。
三、进行编译OpenJDK 8 编译OpenJDK 8的代码很简单,直接make all即可,当然也可以按照README-builds.html中对make执行带参数编译,说明如下:
在编译前还有几个注意事项,这些注意事项在文件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 00:01:46) ----- Build times ------- Start 2018-10-4 10:59:30 End 2018-10-4 11:08:39 00:00:19 corba 00:00:13 demos 00:01:46 docs 00:03:26 hotspot 00:00:18 images 00:00:13 jaxp 00:00:17 jaxws 00:02:01 jdk 00:00:25 langtools 00:00:11 nashorn 00:09:09 TOTAL ------------------------- Finished building OpenJDK for target 'all' 看到这样的结果,表示编译OpenJDK 8成功,可以到多个目录下的bin目录执行./java -version来验证: linux@linux:~/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.0-internal-linux_2018_10_4_11_12-b00) OpenJDK 64-Bit Server VM (build 25.71-b00, mixed mode) linux@linux:~/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.0-internal-linux_2018_10_4_11_12-b00) OpenJDK 64-Bit Server VM (build 25.71-b00, mixed mode)
附,遇到的问题及解决方法 事实上,我在编译的过程中就不顺利,主要遇到了两个问题。 1、编译内核版本问题 在本文中已经提到了两种获取源码的方式,其实一开始我采用的是方法二,下载的是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:127:18: 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,JDK都不打算修复此问题,会在11版本修复这个BUG,所以当前只能通过其他的方式来解决,解决方案如下: 在./hotspot/make/linux/makefiles/gcc.make文件中找到WARNINGS_ARE_ERRORS = -Werro,注释该段或改成WARNINGS_ARE_ERRORS = -Wno-all。再编译就会忽略掉警告,直到编译完成。
相关主题 |