Debug OpenJDK

环境

  • 系统: ubuntu 18.10
  • 编辑器: vscode
  • JDK版本: openjdk8u

下载Openjdk

各版本都在https://hg.openjdk.java.net,这里选择jdk8u。

1
2
3
4
hg clone https://hg.openjdk.java.net/jdk8u/jdk8u openjdk
cd openjdk
chmod u+x get_source.sh
./get_source.sh

hg命令需要事先安装Mercurial.

1
sudo apt install mercurial

如果下载缓慢尝试设置代理,在/etc/mercurial/hgrc文件里加入(真的非常慢):

1
2
3
4
5
6
# system-wide mercurial configuration file
# See hgrc(5) for more information
[http_proxy]
host=host:port
[https_proxy]
host=host:port

编译

编译jdk需要系统已经安装了JDK,称为bootstrap jdk(而且最好是前一个版本,比如编译jdk8,那么事先装好jdk7),如果不对可以通过修改环境变量或者加上configure参数--with-boot-jdk参数指定jdk路径。

1
2
3
4
java -version
openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-1ubuntu0.18.10.1-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)

安装依赖(参考README,也可以configure之后依据提示安装):

1
sudo apt-get install libx11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev libcups2-dev

配置:

1
2
chmod u+x configure
$ ./configure --enable-debug --with-native-debug-symbols=external

debug-level分slowdebug和fastdebug,–enable-debug默认位fast-debug,debug symbol默认是压缩的,设置–with-native-debug-symbols=external免去手动解压的工作。

hotspot/make/linux/makefiles/gcc.make中的WARNINGS_ARE_ERRORS = -Werror改为WARNINGS_ARE_ERRORS = -w,不然会出现如下异常。

1
cc1plus: all warnings being treated as errors

编译:

1
make all

完成

1
2
3
4
build/linux-x86_64-normal-server-fastdebug/jdk/bin/java -version
openjdk version "1.8.0-normal-fastdebug"
OpenJDK Runtime Environment (build 1.8.0-internal-fastdebug)
OpenJDK 64-Bit Server VM (build 25.71-b00-fastdebug, mixed mode)

调试

vscode需要先装上cpptools插件,可以直接在插件商城里搜索c/c++

打开VSCode, File -> OpenFolder选中jdk文件夹,点击左侧虫虫图标,点击add configuration选中c/c++ (gdb) Launch,修改lauch.json文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/linux-x86_64-normal-server-slowdebug/jdk/bin/java",
"args": ["-cp", "~/Desktop","Hello"],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
//"sourceFileMap":{"/build/glibc-YYA7BZ/glibc-2.31": "/usr/src/glibc/glibc-2.31"}
}
]
}

这里主要修改program参数和args参数,program设置为build/linux-x86_64-normal-server-fastdebug/jdk/bin/java,args设置为编译好的class类名(我放在桌面),断点打在src/share/vm/prims/jni.cpp文件下的JNI_CreateJavaVM函数上,这里是jvm的入口,你也可以打在jdk/src/share/bin/main.c 的main函数上,这样差不多就可以开始调了,但是查看文件会非常多的错误提示找不到文件。

接下来在.vscode文件夹下创建c_cpp_properties.json文件,输入以下内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/hotspot/src/**", //hotspot源文件
"${workspaceFolder}/build/linux-x86_64-normal-server-slowdebug/hotspot/linux_amd64_compiler2/generated/**", //编译生成的代码
"${workspaceFolder}/jdk/src/**", //jdk根目录,其中包括大部分的可执行文件的源文件比如java,javac,还有一些native方法的实现
"/usr/src/glibc/glibc-2.31/**" , //libc源代码
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c99",
"cppStandard": "c++98",
"intelliSenseMode": "gcc-x64"
}
],
"version": 4
}

最后一个问题就是调试遇到libc里的函数的时候会弹窗提示找不到对应的文件,首先按照系统提示安装对应版本的glibc源文件,也可以手动下载。

1
sudo apt-get install glibc-source

我这里版本是glibc-2.31,安装在/usr/src/glibc/glibc-2.31.tar.xz,解压在当前目录。

1
2
cd /usr/src/glibc
tar -xvf glibc-2.29.tar.xz

接下来,在弹错误的时候注意提示文件路径,比如我这里是/build/glibc-KRRWSm/glibc-2.29,在launch.jsonconfigurations里面加入"sourceFileMap":{"/build/glibc-KRRWSm/glibc-2.29": "/usr/src/glibc/glibc-2.29"}sourceFileMap配置可以参考下面的文档:https://github.com/vadimcn/vscode-lldb/blob/master/MANUAL.md#source-path-remapping