JDK17编译指南:从源码到定制化JVM
2026/8/9 6:39:44 网站建设 项目流程

1. 为什么需要自己编译JDK17?

在开始动手之前,我们先聊聊为什么要自己编译JDK。很多人可能会问:直接从官网下载编译好的二进制包不香吗?确实,对于大多数开发者来说,直接使用预编译的JDK是最方便的选择。但如果你遇到以下场景,自己编译JDK就变得很有必要了:

  • 你需要为特定硬件平台(如ARM架构)定制JDK
  • 你想修改或扩展JDK的某些功能(比如添加新的JVM参数)
  • 你需要调试JDK内部的实现细节(比如研究HotSpot虚拟机的工作原理)
  • 你想为JDK贡献代码(OpenJDK是开源的,欢迎社区贡献)

我最近就因为需要研究JVM的GC日志实现细节,不得不自己编译JDK。在这个过程中踩了不少坑,也积累了一些经验,下面就把完整的编译过程分享给大家。

2. 编译环境准备

2.1 硬件要求

编译JDK是个资源密集型任务,建议准备:

  • 至少16GB内存(32GB更佳)
  • 至少100GB可用磁盘空间(SSD最佳)
  • 多核CPU(8核以上能显著缩短编译时间)

提示:如果机器配置不够,可以尝试减少并行编译线程数,但编译时间会大幅增加。

2.2 操作系统选择

官方支持的平台包括:

  • Linux(推荐Ubuntu 20.04 LTS)
  • macOS(10.13及以上)
  • Windows(需要WSL2或Cygwin)

我个人推荐使用Linux系统,因为:

  1. 依赖管理更方便
  2. 编译环境更接近生产环境
  3. 问题排查资料更丰富

2.3 软件依赖安装

以Ubuntu 20.04为例,需要安装以下依赖:

sudo apt update sudo apt install -y git build-essential libx11-dev libxext-dev libxrender-dev \ libxtst-dev libxt-dev libcups2-dev libfontconfig1-dev libasound2-dev \ libfreetype6-dev autoconf zip unzip

如果是其他系统,可以参考OpenJDK官方文档中的 构建要求 。

3. 获取JDK17源码

3.1 克隆OpenJDK仓库

JDK17的源码托管在GitHub上:

git clone https://github.com/openjdk/jdk17u.git cd jdk17u

如果网络连接不稳定,可以考虑使用国内镜像:

git clone https://gitee.com/mirrors/openjdk-jdk17u.git

3.2 选择正确的分支

JDK17有多个更新版本,建议选择最新的稳定分支:

git checkout jdk-17.0.6+10 # 以最新发布的更新版本为准

可以通过git tag -l查看所有可用版本。

4. 配置编译环境

4.1 设置Bootstrap JDK

编译JDK17需要一个已有的JDK作为引导(Bootstrap JDK),要求版本为JDK16或JDK17:

sudo apt install openjdk-17-jdk export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64

验证Bootstrap JDK:

$JAVA_HOME/bin/java -version

应该输出类似以下内容:

openjdk version "17.0.6" 2023-01-17 OpenJDK Runtime Environment (build 17.0.6+10) OpenJDK 64-Bit Server VM (build 17.0.6+10, mixed mode)

4.2 运行配置脚本

JDK使用Autoconf系统进行配置:

bash configure --enable-debug --with-jvm-variants=server

常用参数说明:

  • --enable-debug:生成带调试信息的版本
  • --with-jvm-variants=server:编译server版JVM(默认)
  • --disable-warnings-as-errors:将警告视为非致命错误

如果配置成功,会输出类似以下信息:

Configuration summary: * Debug level: fastdebug * HS debug level: fastdebug * JVM variants: server * OpenJDK target: OS: linux, CPU architecture: x86, address length: 64

5. 开始编译

5.1 执行编译命令

使用make命令开始编译:

make images

这个命令会编译出完整的JDK镜像,包括:

  • 完整的JDK(在build/linux-x86_64-server-fastdebug/images/jdk
  • 精简的JRE(在build/linux-x86_64-server-fastdebug/images/jre

5.2 控制编译过程

  • 查看编译进度:make LOG=info images
  • 并行编译(加快速度):make JOBS=4 images(根据CPU核心数调整)
  • 只编译HotSpot VM:make hotspot
  • 只编译javac编译器:make java.compiler

编译过程可能需要30分钟到数小时,取决于机器性能。

6. 验证编译结果

6.1 检查编译产物

编译完成后,可以验证生成的JDK:

./build/linux-x86_64-server-fastdebug/images/jdk/bin/java -version

应该输出类似:

openjdk version "17-internal" 2021-09-14 OpenJDK Runtime Environment (fastdebug build 17-internal+0-adhoc.user.jdk17u) OpenJDK 64-Bit Server VM (fastdebug build 17-internal+0-adhoc.user.jdk17u, mixed mode)

注意这里的版本号包含"internal"和"fastdebug",表示这是我们自己编译的调试版本。

6.2 运行测试用例

为了确保编译的JDK功能正常,可以运行一些基本测试:

make test-tier1

这个命令会运行一组基本的JVM和核心库测试。

7. 常见问题与解决方案

7.1 编译失败:缺少依赖

错误示例:

checking for freetype... configure: error: Could not find freetype!

解决方案:

sudo apt install libfreetype6-dev

7.2 内存不足

错误示例:

g++: fatal error: Killed signal terminated program cc1plus

解决方案:

  1. 增加swap空间
  2. 减少并行编译线程:make JOBS=2 images

7.3 版本不匹配

错误示例:

error: The supplied boot JDK (version 16) is not a valid JDK 17 image.

解决方案:确保使用JDK17作为Bootstrap JDK。

8. 高级技巧

8.1 增量编译

修改源码后,可以只重新编译变更部分:

make hotspot

8.2 生成IDE项目文件

生成Eclipse项目文件:

make eclipse-project

生成IntelliJ IDEA项目文件:

make ide-project

8.3 调试JVM

编译debug版本后,可以使用gdb调试JVM:

gdb --args ./build/linux-x86_64-server-fastdebug/images/jdk/bin/java -version

9. 实际应用场景

9.1 修改JVM参数

假设我们想添加一个自定义的JVM参数:

  1. 修改src/hotspot/share/runtime/globals.hpp,添加:
experimental(intx, MyCustomParam, 100, \ "A custom parameter for testing") \
  1. 重新编译HotSpot:
make hotspot
  1. 使用新参数:
./build/linux-x86_64-server-fastdebug/images/jdk/bin/java -XX:+UnlockExperimentalVMOptions -XX:MyCustomParam=200

9.2 添加新的JNI方法

如果想在JDK中添加新的native方法:

  1. 在Java类中声明native方法
  2. 生成头文件:javac -h ...
  3. 在对应native文件中实现方法
  4. 重新编译对应模块

10. 性能优化建议

10.1 使用ccache加速编译

安装ccache:

sudo apt install ccache

配置环境变量:

export CC="ccache gcc" export CXX="ccache g++"

10.2 选择性编译

如果只研究特定模块,可以只编译相关部分:

  • 只编译核心库:make java.base
  • 只编译NIO模块:make java.nio

10.3 使用tmpfs

将编译目录挂载到内存文件系统:

sudo mount -t tmpfs -o size=20G tmpfs /path/to/build/dir

这能显著提高编译速度,但需要足够的内存。

11. 后续学习建议

成功编译JDK只是开始,如果想深入理解JDK实现:

  1. 从java.base模块开始阅读源码
  2. 重点关注:
    • HotSpot虚拟机实现
    • 核心类库(如java.lang, java.util)
    • JNI机制
  3. 使用调试器单步跟踪关键流程(如类加载、方法调用)
  4. 参与OpenJDK社区讨论和贡献

我自己在阅读JDK源码时,发现从JVM启动流程(main.c的JLI_Launch方法)开始跟踪是个不错的切入点。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询