openjdk11源码从编译到clion调试

1. 概述

先声明环境:

  1. Ubuntu18
  2. 安装并配置好JDK11(openjdk version “11.0.1” 2018-10-16)
  3. 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+NCtrl+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. 前期准备

  1. 编译需要boot jdk(低版本貌似不行,建议11),所以必须配置好jdk相关环境变量。
  2. 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不会。

  1. 我们需要在项目根目录下手动创建一个CMakeLists.txt,然后写入如下内容:
    cmake_minimum_required(VERSION 3.14) # 这个设置不需要严格对应,自己建个测试项目复制过来这段即可
    
    project(hotspot)
    
    file(GLOB_RECURSE SOURCE_FILES "*.cpp" "*.hpp" "*.c" "*.h")
    
    add_executable(hotspot ${SOURCE_FILES})
    
  2. reload changes重新加载CMakeLists.txt就会自动生成一个名称为hotspot的Run Configuration,类型为CMake Application。

5.2. 更改Run Configuration

但是这样是不够的,无法启动,我们需要修改Run configuration

  1. 将Executable修改为我们编译生成的build/linux-x86_64-normal-server-release/jdk/bin/java程序
  2. 将下面的Before Launch下的build删除掉

openjdk11源码从编译到clion调试_第1张图片
现在就可以利用这个配置进行调试了,可以利用Program arguments像平时一样给java命令传递参数。

5.3. 打断点

打开share/prims/jni.cpp,给JNI_CreateJavaVM函数打断点。以调试模式运行:
openjdk11源码从编译到clion调试_第2张图片
我们可以像平时调试一样单步进入、查看调用栈、查看运行线程、查看参数信息等
openjdk11源码从编译到clion调试_第3张图片

我们的调试之旅就到这里了,有什么问题欢迎留言

6. 推荐资料

  • 【JVM源码探秘系列】HotSpot启动流程分析-初始化 - WorkHoliday 的个人博客
  • 利用Ubuntu18编译openjdk11 - 明月逐人归 的个人博客
  • mac下编译openjdk1.9及集成clion动态调试 - 闪电侠 - 简书

你可能感兴趣的:(Java,源码阅读)