YON Blog

Mac 调试编译 OpenJDK9

几年前花费了很大精力在 Mac 下把 JDK7 编译了出来, 中间踩了无数的坑, 前几天想编译调试 JDK9 看看各种锁优化的实现. 本以为参考下之前的文章很快就能编译出来, 没想到很多工具都已经失效, Mac 系统的更新更是让编译雪上加霜.

放心, 这篇文章不会又是一篇填坑指南. 我自己填坑的时候忽然想到, 为什么不在 Docker 里编译呢?

使用 Docker 的好处就是环境统一, 另外采用 Linux 系统, 构建起来也更方便, 缺什么就安装什么. 下面就是我用的可以成功编译 OpenJDK9 的 Dockerfile:

FROM ubuntu:18.04

RUN apt update && \
    apt install -y vim gdb file build-essential unzip zip \
    openjdk-8-jdk libx11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev \
    libcups2-dev libfreetype6-dev libasound2-dev libelf-dev

CMD bash


编译环境有了, 还缺的就是源码了, 有很多下载方式, 我是从这里下载的 http://jdk.java.net/java-se-ri/9.

假设你下载解压后的代码放在 ~/Downloads/openjdk . 现在我们启动 Docker:

docker run -v ~/Downloads/openjdk:/openjdk -it -p 1234:1234 --rm --security-opt seccomp=unconfined jdkbuilder

其中 --security-opt seccomp=unconfined 是为了让后面用 gdb 顺利调试用的. 映射 1234 端口是为了后面远程 Debug.

启动镜像后, 切换到 /openjdk 目录, 执行下面命令:

 bash configure --with-jvm-variants=server \
     --disable-warnings-as-errors \
     --with-debug-level=slowdebug \
     --with-native-debug-symbols=internal

--with-debug-level=slowdebug 和 --with-native-debug-symbols=internal 是为了之后调试用的, --disable-warnings-as-errors 是让编译器忽略 warning, --with-jvm-variants=server 是编译服务器版本的 jvm.

configure 如果顺利执行, 就可以用 make images 来开始编译了, 我 docker 用 6 核 8 G 内存大概要 1 个多小时.

如果一切顺利, 编译好的 jdk 就在 /openjdk/build/.../jdk 下面, 可以用 gdb --args ./java -version 来试着调试. 调试的时候会提示有 received signal SIGSEGV, Segmentation fault. 的错误, 不用管, 直接 continue 就行.

如果觉得用 gdb 不方便, 也可以在 Docker 里启动 gdbserver 后用 CLion 远程 Debug:

# 容器里启动 gdbserver
gdbserver :1234 ./java -version

CLion 里创建一个 GDB Remote Debug 的配置, target 里填入: 127.0.0.1:1234 . Path mappings 里, Remote 填入 /openjdk, Local 里填入你对应的本地地址 /Users/.../Downloads/openjdk .

CLion 支持一整套的远程开发流程了, 包括代码同步, 编译, 部署, 调试. 不过只支持 CMake 的项目, 我就懒得弄了, 反正就是准备简单看看代码调试的, 而且 CLion 我也只是试用版, 就用 GDB 从命令行调试得了.