JVM之路(一)编译属于自己的 JDK

一、编译环境及背景

本文是参照《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》 周志明老师的书来实践学习的,站在巨人的肩膀上!!
对于阅读本书,我的体会是:有的地方第一次读很难理解,甚至通过去各种论坛也只能摸到门槛,但是随着学习的不断深入,会发现前面的一些描述其实在后面有专门的讲解,这也是无法避免的,因为人一旦学会某些东西,便很难以初学者的角度去讲解,希望能耐下性子,多看几遍书。

以下是书中与实际操作的环境对比:

实践环境书中环境
系统RHEL8Ubuntu 18.04 LTS
JDKJDK12_06222165c35fJDK12_06222165c35f
本地运行测试代码 JDK1.8.0_301

因此,在实际操作中会与书中有差异,但差异代表着我需要对每一步操作有更深的理解,排除出现的问题,fighting!!!
着重提一点,源代码目录/doc/building.html 文件或者 building.md 文件强烈推荐看一看,对于编译的理解以及处理不同操作系统环境准备非常有帮助

软件版本
GCC8.4.1-1.el8
FreeType2.9.1-4.el8_3.1
CUPS1:2.2.6-38.el8
X11libXtst-devel-1.2.3-7.el8.x86_64;libXt-devel-1.1.5-12.el8.x86_64;libXrender-devel-0.9.10-7.el8.x86_64;libXrandr-devel-1.5.2-1.el8.x86_64;libXi-devel-1.7.10-1.el8.x86_64
ALSA1.2.4-5.el8
libffi3.1-22.el8
Autoconf2.69-27.el8

二、上手实操

我这里将编译 JDK 的步骤分为如下:

  1. 下载 JDK 源码
  2. 安装编译依赖环境与 Boot JDK
  3. 编译操作

2.1 下载 JDK 源码

下载之前首先要区分一下:
https://hg.openjdk.java.net/jdk/jdk12/file/06222165c35f :二进制源码
https://jdk.java.net/java-se-ri/12:编译好的 JDK

  1. 进入源码下载网站https://hg.openjdk.java.net/,选择 jdk -> jdk12,点击 browse 查看到的即是源码目录;
  2. 点击左侧的 zip/gz 来下载不同版本的源码压缩包;
    在这里插入图片描述
压缩包大小
jdk12-06222165c35f.tar.gz103M
jdk12-06222165c35f.zip171M

2.2 构建编译环境

环境分为 GCC 编译器、OpenJDK 编译依赖库、Bootstrap JDK,这一章节如果书中没有设计到你所用系统,请参阅源码目录/doc/building.md

2.2.1 GCC编译器

For apt-based distributions (Debian, Ubuntu, etc), try this:

sudo apt-get install build-essential

For rpm-based distributions (Fedora, Red Hat, etc), try this:

sudo yum groupinstall "Development Tools"

2.2.2 OpenJDK编译依赖库

工具库名称
FreeTypeThe FreeType Project
CUPSCommon UNIX Printing System
X11X Window System
ALSAAdvanced Linux Sound Architecture
libffiPortable Foreign Function Interface Library
AutoconfExtensible Package of M4 Macros

安装命令如下,根据系统版本选择安装

FreeType

  • To install on an apt-based Linux, try running sudo apt-get install libfreetype6-dev.
  • To install on an rpm-based Linux, try running sudo yum install freetype-devel.
  • To install on Solaris, try running pkg install system/library/freetype-2.

CUPS

  • To install on an apt-based Linux, try running sudo apt-get install libcups2-dev.
  • To install on an rpm-based Linux, try running sudo yum install cups-devel.
  • To install on Solaris, try running pkg install print/cups.

X11

  • To install on an apt-based Linux, try running sudo apt-get install libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev.
  • To install on an rpm-based Linux, try running sudo yum install libXtst-devel libXt-devel libXrender-devel libXrandr-devel libXi-devel.
  • To install on Solaris, try running pkg install x11/header/x11-protocols x11/library/libice x11/library/libpthread-stubs x11/library/libsm x11/library/libx11 x11/library/libxau x11/library/libxcb x11/library/libxdmcp x11/library/libxevie x11/library/libxext x11/library/libxrender x11/library/libxrandr x11/library/libxscrnsaver x11/library/libxtst x11/library/toolkit/libxt.

ALSA

  • To install on an apt-based Linux, try running sudo apt-get install libasound2-dev.
  • To install on an rpm-based Linux, try running sudo yum install alsa-lib-devel.

libffi

  • To install on an apt-based Linux, try running sudo apt-get install libffi-dev.
  • To install on an rpm-based Linux, try running sudo yum install libffi-devel.

Autoconf

  • To install on an apt-based Linux, try running sudo apt-get install autoconf.
  • To install on an rpm-based Linux, try running sudo yum install autoconf.
  • To install on macOS, try running brew install autoconf.
  • To install on Windows, try running <path to Cygwin setup>/setup-x86_64 -q -P autoconf.

2.2.3 Bootstrap JDK

要编译大版本号为 N 的 JDK ,我们还要另外准备一个大版本号至少为 N-1 的、已经编译好的 JDK,因为 OpenJDK 中许多 Java 语言编写的代码需要在编译器执行,所以需要一个编译器可用的 JDK,官方称为 Bootstrap JDK;这里我们需要安装 JDK11

  • To install on an apt-based Linux, try running sudo apt-get install openjdk-11-jdk.
  • To install on an rpm-based Linux, try as below.

因为我使用的是 RHEL8 ,所以我采用一下的方式搜索需要安装版本的:

[root@linuxprobe ~]# dnf search jdk | grep java-11-*		## 查找对应的软件包名
Last metadata expiration check: 8:14:39 ago on Mon 27 Sep 2021 02:27:51 PM CST.
java-11-openjdk.x86_64 : OpenJDK 11 Runtime Environment
java-11-openjdk-demo.x86_64 : OpenJDK 11 Demos
java-11-openjdk-devel.x86_64 : OpenJDK 11 Development Environment
java-11-openjdk-headless.x86_64 : OpenJDK 11 Headless Runtime Environment
java-11-openjdk-javadoc.x86_64 : OpenJDK 11 API documentation
java-11-openjdk-javadoc-zip.x86_64 : OpenJDK 11 API documentation compressed in a single archive
java-11-openjdk-jmods.x86_64 : JMods for OpenJDK 11
java-11-openjdk-src.x86_64 : OpenJDK 11 Source Bundle
java-11-openjdk-static-libs.x86_64 : OpenJDK 11 libraries for static linking

## 这两个包就是我们需要安装的 Bootstrap JDK
dnf install -y java-11-openjdk
dnf install -y java-11-openjdk-devel

2.3 编译操作

将 JDK12 包复制到 linux 目录中(/opt/jvm/),并解压缩;编译操作分为两步,一是环境准备,二是编译 JDK;
configure命令承担了步骤一依赖项检查、参数配置和构建输出目录结构等多项职责,如果编译过程中需要的工具链或者依赖项有缺失,命令执行后将会得到明确的提示,并且给出该依赖的安装命令,属于“友好型”;

注意,在多次编译,或者目录结构构建成果(configure运行成果)后再次修改配置,必须先使用 make cleanmake dist-clean 命令清理目录

在 JDK 目录下运行编译命令:

  1. 编译FastDebug版、仅含Server模式的HotSpot虚拟机:bash configure --disable-warnings-as-errors --enable-debug --with-jvm-variants=server
  2. 编译整个 OpenJDK:make images
    [root@linuxprobe jdk12-06222165c35f]# pwd
    /opt/jvm/jdk12-06222165c35f
    [root@linuxprobe jdk12-06222165c35f]# bash configure --disable-warnings-as-errors --enable-debug --with-jvm-	variants=server
    [root@linuxprobe jdk12-06222165c35f]# make images
    

编译后的文件就在 JDK目录/build 下,其文件目录介绍如下:
在这里插入图片描述
*上方使用的 make images 执行的是整个 OpenJDK 编译,这里 “images” 是 “productimages” 编译目标(Target)的简写别名,这个目标的作用是编译出整个 JDK 镜像,除了 “productimages” 以外;除此外 make 还有以下用法:

hotspot:只编译HotSpot虚拟机
hotspot-:只编译特定模式的HotSpot虚拟机
docs-image:产生JDK的文档镜像
test-image:产生JDK的测试镜像
all-images:相当于连续调用product、docs、test三个编译目标
bootcycle-images:编译两次JDK,其中第二次使用第一次的编译结果作为Bootstrap JDK
clean:清理make命令产生的临时文件
dist-clean:清理make和configure命令产生的临时文件

三、问题回顾

我所遇到的问题有两个:

  1. 因为系统源JDK安装的是 JDK8u302,我直接使用 dnf remove java 卸载之前安装的jdk,然后dnf search jdkdnf install java-11-openjdk 查找和安装 JDK11,然后就开始问题发现之旅:

    a. 查看 java 版本发现仍为 1.8 版本,先对环境变量进行修改::

    449  echo $JAVAHOME		# 查看环境变量,发现环境变量仍然配置的1.8
    450  echo $PATH			# 查看默认加载java路径,发现路径也未修改,因为引用了JAVA_HOME
    451  echo $CLASSPATH	
    
    # vim /etc/profile 修改环境变量
    export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-11.0.12.0.7-0.el8_4.x86_64
    export PATH=$PATH:$JAVA_HOME/bin
    

    b. 检查旧版 JDK 安装包是否全部清理,如有残余则全部清理掉:

    dnf list installed | grep jdk	# 列出所有安装的 jdk 相关软件包
    dnf remove java-1.8.0-openjdk*	# 清理 java-1.8.0-openjdk 相关的软件包
    

    由此,环境 JDK 已经跟换为 11 版本;

  2. 出现的错误如下,本以为是 arguments.cpp 的导致的问题,后经仔细查阅,其实为下方红框中cclplus: all warnings being treated as errors,GCC在8.0之后的版本加入了stringop truncation的验证警告,所有这里是因为出现了警告导致编译不通过,由此提醒了我,对于软件版本的监控需要注意,我将会在页首加上各软件版本的信息;

    在这里插入图片描述
    这里将原先的bash configure --enable-debug --with-jvm-variants=server
    替换为:bash configure --disable-warnings-as-errors --enable-debug --with-jvm-variants=server 即可解决问题

最后,附上一个编译成功后查看编译版本的截图:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mitays

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值