前言
最近在看周志明老师的经典《深入理解Java虚拟机》,第1章最后是一个自己编译JDK的实战,想到羊哥之前也出过这样一期视频,觉得做一做也蛮有成就感的,还可以加深下对Java的理解,所以边做边写下此篇博文。
环境准备
系统环境
我的环境是macOS10.14.6(黑苹果),问题相对Windows应该会少很多,推荐大家也是用Linux或者macOS来进行编译。
Xcode下载
一些C/C++相关的工具链一般是用Xcode带的,所以去官网下载就行。但是如果像我一样是黑苹果,系统不是最新的,官网的版本很可能不适配(目前最新Xcode 13要求macOS 11以上),所以只能翻到以前百度云里存的Xcode11.xip下载解压并安装就可以了。
xip文件在解压时需要用系统自带的解压工具,不要用第三方的,不然解压出来不是一个.app文件。
还有就是解压时可能会遇到系统验证问题,通过以下两步解决:
- 运行以下命令行
# 最后是xip文件的位置
xattr -d com.apple.quarantine Xcode_11.xip
- 在系统设置中修改系统的时间约为2018年7月,然后允许任何来源的软件安装。
所有软件环境基础
以下都是编译中需要用到的软件环境,确保都已经安装
# 有一个已经可用的jdk,版本至少是要编译的版本-1
java -version
# 输出
openjdk version "11.0.9" 2020-10-20
OpenJDK Runtime Environment (build 11.0.9+11)
OpenJDK 64-Bit Server VM (build 11.0.9+11, mixed mode)
# C的编译器
clang --version
# 输出
Apple clang version 11.0.0 (clang-1100.0.33.8)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
# C++的编译器
clang++ --version
# 输出
Apple clang version 11.0.0 (clang-1100.0.33.8)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
# 自动配置工具autoconf
# 下载方式:brew install autoconf
autoconf --version
# 输出
autoconf (GNU Autoconf) 2.69
# 编译构建工具
make --version
# 输出
GNU Make 3.81
# 渲染库freetype
freetype-config --ftversion
# 输出
2.10.4
源码下载
这次要编译的目标版本是jdk11,所以下载jdk11的源码
方式一:通过Mercurial
JDK是通过这个叫Mercurial的版本管理工具来进行代码管理的,这个和git是一类工具,只不过过于小众。而且这种方式慢,不推荐。
- 安装Mercurial
brew install mercurial
-
去网址hg.openjdk.java.net上复制地址
-
使用命令clone源码包
hg clone https://hg.openjdk.java.net/jdk/jdk11/
方式二:官网下载压缩包
这种方式速度快,推荐这种方式
前往地址:
Java Platform, Standard Edition 11 Reference Implementations
点击下载zip压缩包即可
新建一个专门的文件夹存放源码包,解压后就可以看到目录结构
src就是源码部分,看到里面基本都是C和C++的代码,说明Java就是用C和C++写的。
自动配置工作
这一步进行编译前的自动编译工作
# 首先cd进源码目录,也就是上图的openjdk11
cd openjdk11
# 运行脚本
sh configure
这个过程较快,最后会输出一些概览信息。
正式编译工作
第一次编译直接进行全量编译,执行:
make all
这个过程比较久,耐心等待,会生成可执行文件,JDK成品镜像等很多东西
过程中的警告可以忽略,只要不出现错误导致整个过程停止即可
可以看到这个过程中我的mac的活动监视器,CPU快要炸了
直到控制台最后几行输出一下信息就证明成功了
Creating support/demos/image/jfc/SampleTree/SampleTree.jar
Creating support/demos/image/jfc/TableExample/TableExample.jar
Creating support/demos/image/jfc/TransparentRuler/TransparentRuler.jar
Creating jdk image
Finished building target 'all' in configuration 'macosx-x86_64-normal-server-release'
成品验收
完成上一步后就可以发现目录下多了一个build目录,进入build/macosx-x86_64-normal-server-release/
目录可以看到如下文件
命令行验证下
# 进入编译后的jdk的bin目录
cd build/macosx-x86_64-normal-server-release/jdk/bin
# 执行java命令查看版本
./java -version
# 输出
openjdk version "11-internal" 2018-09-25
OpenJDK Runtime Environment (build 11-internal+0-adhoc.ccqstark.openjdk11)
OpenJDK 64-Bit Server VM (build 11-internal+0-adhoc.ccqstark.openjdk11, mixed mode)
最终的JDK成品就在images/jdk
目录下,这个就和我们平时在官网上下载的JDK基本是一样的
IDEA中使用新JDK
新建一个Hello World项目
添加自己编译的JDK的路径
切换项目所用的JDK为刚刚新增的
运行之后可以看到我们使用的JDK已经换成自己编译得到的了
定制JDK
当我们需要自己定制一套属于自己的JDK的时候就需要我们去修改源码中的一些实现,修改之后要生效的话必须重新编译一次,这次的编译就可以用增量编译了。
修改Sourcepath
删除原来全部路径
重新添加我们一开始下载的压缩包中解压出来的src
目录下的源码,并让IDEA重新索引
修改源码
我们Ctrl加鼠标点击进入println源码,并做点修改意思意思
增量编译
再次cd到解压出来的大目录下,执行
make images
进行增量编译,速度会比全量编译快
再次运行代码发现之前对源码的修改已经生效
参考资料
- 《深入理解Java虚拟机》 周志明
- JDK都没手动编译过,敢说自己是Java程序员吗?实战编译Java源码(JDK源码,JVM)视频教程 CodeSheep