1. 概述
先声明环境:
- Ubuntu18
- 安装并配置好JDK11(openjdk version “11.0.1” 2018-10-16)
- Clion2019.2
可以在docker里面编译,利用ubuntu的镜像,然后安装相关依赖也不会影响到宿主机。
2. 下载OpenJDK11
其实我们搜索openjdk进入到jdk11特性列表页面时,左边有个Mercurial链接,从那就可以进入源码列表了,在源码列表选择jdk->jdk11即进入了源码页面。
最终源码链接在此 https://hg.openjdk.java.net/jdk/jdk11/。
打开后选择左边的bz2或zip或gz格式的下载文件即可。
这里我们选择bz2(总共87MB)格式的文件,即最终下载链接在此 https://hg.openjdk.java.net/jdk/jdk11/archive/tip.tar.bz2。
特意提供百度网盘链接 https://pan.baidu.com/s/1w91BX7-rF-6F1Dd_zly7dA 提取码: 7a7k
之后就是解压到特定无特殊字符名的文件夹了,就不再赘述了。
3. 目录结构
解压后目录结构大致就是这样
.
├── ADDITIONAL_LICENSE_INFO
├── ASSEMBLY_EXCEPTION
├── bin
├── build
├── configure //利用bash configure来做编译前的准备工作
├── doc //里面有各种帮助文件,可以教你怎么编译jdk
├── LICENSE
├── make
├── Makefile
├── README
├── src //主要源码
└── test
3.1. src的目录结构
我们用clion打开解压后的目录(src目录的父目录),等待扫描后,就可以利用Ctrl+Shift+N
或Ctrl+Shift+F
等快捷键快速搜索文件名或特定字符串。
.
├── bsd
├── demo
├── hotspot
├── java.base
├── java.compiler
├── java.datatransfer
├── java.desktop
├── java.instrument
├── java.logging
....同类省略
├── jdk.accessibility
├── jdk.aot
├── jdk.attach
├── jdk.charsets
...同类省略
├── linux
├── sample
├── solaris
└── utils
其中hotspot 就是Java虚拟机的Cpp源码了,我们调试就只需要利用这个目录下的文件即可。
如果想查看Java类中的本地方法是怎么实现的,只需打开相应的文件夹找到相应的类名.c文件即可。
例如:查看String类的intern方法的实现。利用Ctrl+Shift+N
打开文件名搜索string.c
,即可看到src/java.base/share/native/libjava/String.c
中的intern实现。
JNIEXPORT jobject JNICALL
Java_java_lang_String_intern(JNIEnv *env, jobject this)
{
return JVM_InternString(env, this);
}
4. 编译JDK
官方的编译jdk的文档在doc/building.md
,通过这个可以了解很多信息。
4.1. 前期准备
- 编译需要boot jdk(低版本貌似不行,建议11),所以必须配置好jdk相关环境变量。
- gcc/g++也是要的
实际上到这你就可以在解压目录下执行bash configure --disable-warnings-as-errors
(后面的选项一定要加上,否则编译不通过)。然后你会发现总是报错不通过并提示未安装相应文件,只需根据提示安装即可。如:
configure: error: Could not find alsa! You might be able to fix this by running 'sudo apt-get install libasound2-dev'
重复步骤直到成功即可。
4.2. 正式编译
实际上可以执行
make help
,会显示编译帮助
执行make
。
.....
Stopping sjavac server
Finished building target 'default (exploded-image)' in configuration 'linux-x86_64-normal-server-release'
编译成功后的显示如上。
编译好的jdk文件会在build/linux-x86_64-normal-server-release/jdk
目录下,根我们平时下的jdk目录结构是一样的。
5. 调试JVM
之前我们已经利用clion在解压目录下(src目录的父目录)打开了项目。现在我们close project
,然后再次file->open
打开src/hotspot
目录。
5.1. 创建CMakeLists.txt
以前的Clion好像会自动生成CMakeLists.txt
,我用的Clion2019.2不会。
- 我们需要在项目根目录下手动创建一个
CMakeLists.txt
,然后写入如下内容:cmake_minimum_required(VERSION 3.14) # 这个设置不需要严格对应,自己建个测试项目复制过来这段即可 project(hotspot) file(GLOB_RECURSE SOURCE_FILES "*.cpp" "*.hpp" "*.c" "*.h") add_executable(hotspot ${SOURCE_FILES})
- reload changes重新加载
CMakeLists.txt
就会自动生成一个名称为hotspot的Run Configuration
,类型为CMake Application。
5.2. 更改Run Configuration
但是这样是不够的,无法启动,我们需要修改Run configuration
。
- 将Executable修改为我们编译生成的
build/linux-x86_64-normal-server-release/jdk/bin/java
程序 - 将下面的Before Launch下的build删除掉
现在就可以利用这个配置进行调试了,可以利用Program arguments像平时一样给java命令传递参数。
5.3. 打断点
打开share/prims/jni.cpp
,给JNI_CreateJavaVM
函数打断点。以调试模式运行:
我们可以像平时调试一样单步进入、查看调用栈、查看运行线程、查看参数信息等
我们的调试之旅就到这里了,有什么问题欢迎留言