OpenJDK-调试 (CLion)

前面的文章

OpenJDK-编译 (mac)

导入项目

1、openjdk 12及以上版本

openjdk-12及以上的版本可以采用compile_commands.json导入,这种方式导入可以解决clion采用生成CMakeLists.txt而部分openjdk源码出现头文件无法找到的问题 JetBrains关于Compilation DataBase的介绍:https://blog.jetbrains.com/clion/2020/03/openjdk-with-clion/

1.1 生成compile-commands.json

在openjdk源码根目录执行make命令,本文档中采用openjdk-16

# 进入openjdk源码根目录
$ cd /Users/saleson/c-projects/jdk-jdk-16-ga 

# 生成compile-commands.json
$ make compile-commands
Compiling ......
Compiling 949 files for jdk.hotspot.agent
Updating compile_commands.json
Stopping sjavac server
Finished building target 'compile-commands' in configuration 'macosx-x86_64-server-slowdebug'

# 或者添加CONF参数,任意一个make命令执行成功即可
$ make CONF=macosx-x86_64-normal-server-slowdebug compile-commands

执行完成后,在{openjdk rootdir}/build/macosx-x86_64-normal-server-slowdebug目标下会生成一个compile-commans.json

$ pwd
/Users/saleson/c-projects/jdk-jdk-16-ga/build/macosx-x86_64-server-slowdebug
$ ls compile_commands.json
compile_commands.json
1.2 CLion通过compile_commands.json导入openjdk源码

打开CLion,操作路径: File > Open > 选择文件

/Users/saleson/c-projects/jdk-jdk-16-ga/build/macosx-x86_64-server-slowdebug/compile_commands.json

点击 open as Project 按钮
在这里插入图片描述
之后CLion会做扫描和index,但是这时候还看不到源码相关的文件和目录,因为此时根目录是/Users/saleson/c-projects/jdk-jdk-16-ga/build/macosx-x86_64-server-slowdebug, 需要更改项目根目录。
操作路径:Tools -> Compilation Database -> Change Project Root
选中openjdk的源码根目录,本文档中的源码根目录是/Users/saleson/c-projects/jdk-jdk-16-ga
CLion再次扫描文件和建立index,结束后就可以看到源码了,且不会提示无法找到头文件
在这里插入图片描述

2、openjdk 11及以下版本

openjdk11及以下的版本比较简单,直接导入就可以了,本文档中使用的是openjdk-11,操作路径如下:
File > New CMake Project from Sources
选择源码根目录,例如:/Users/saleson/c-projects/jdk-jdk-11-28
之后会出现如下界面,这些选项的内容最终会生成到CMakeLists.txt中
在这里插入图片描述
点击OK之后
在这里插入图片描述
通过这种方式导入,仍会有部分源文件上会提示找不到头文件。所以接下来本文档中均采用通过compile-commands.json方式导入的openjdk-16源码来进行调试。

调试

debug之前

需要配置构建目标,操作路径:
Preferences > Build, Exceution, Deployment > Custom Build Targets
在这里插入图片描述
最终打开Edit Tool编辑小面板,其中Tool Settings几个参数内容分别是:

FieldContent
Programmake
ArgumentsCONF=macosx-x86_64-normal-server-slowdebug
Working directory/Users/saleson/c-projects/jdk-jdk-16-ga

调试 java -version

在CLion右上方打开 Edit Configurations面板
在这里插入图片描述
新增Custom Build Application调试 java -version
在这里插入图片描述
Target: 选择前面创建好的Custom Build Target
Executable: 选择编译后的openjdk目录下的{openjdk}/build/macosx-x86_64-normal-server-slowdebug/jdk/bin/java 文件
Propram arguments: java 命令后面跟着的参数,例如:-version

在java.c文件的JavaMain()方法或者jni.cpp文件的JNI_CreateJavaVM_inner()方法上打上断点,点击右上角的debug,然后代码运行会停在断点处。
java.c文件的JavaMain()方法断点:
在这里图片描述
jni.cpp文件的JNI_CreateJavaVM_inner()方法断点:
在这里插入图片描述
执行结果:
在这里插入图片描述

忽略SIGEGV和SIGBUS信号

在调试过程会遇到下面这种情况
在这里插入图片描述
这是由于本案例中CLion采用的是LLDB 进行 debug 的,会处理SIGEGV和SIGBUS信号,避免这个问题的方法是在第一次断点处,在LLDB命令行面板中输入如下命令,就可以避免这个问题

pro hand -p true -s false SIGSEGV SIGBUS

在这里插入图片描述
此时debug的输出面板中就不会再出现 Signal: SIGSEGV (signal SIGSEGV) 这样的信息了
在这里插入图片描述

如果每次debug都要手动运行一次这样的命令也很麻烦,可以生成一个脚本文件。在用户目录下面创建.lldbinit文件

$ vim ~/.lldbinit

内容如下:

br set -n main -o true -G true -C "pro hand -p true -s false SIGSEGV SIGBUS"

这样就可以完美的解决问题了。

调试 java 类

写一个简单的测试代码:

package com.saleson.jdk;

import java.util.concurrent.locks.LockSupport;

/**
 * @author saleson
 * @date 2022-03-31 20:59
 */
public class Demo {

    public static void main(String[] args) throws Exception {
        LockSupport.park();
    }
}

在测试代码中调用LockSupport.park()方法,该方法会再调用Unsafe.park()这个native方法,到unsafe.cpp中定位到Unsafe_Park()方法,在此方法内设置断点
在这里插入图片描述

调试class文件

事先将Demo.java编译成class文件,新建Custom Build Application 进行调试
在这里插入图片描述

FieldContentDescribe
Program{openjdk}/build/macosx-x86_64-normal-server-slowdebug/jdk/bin/java编译openjdk后的java命令
Argumentscom.saleson.jdk.Demo类路径
Working directory/Users/saleson/IdeaProjects/personal/target/classescom.saleson.jdk.Demo 的类目录

看一下断点调试情况
在这里插入图片描述

调试java文件

接下来选择使用java文件来进行调试,比之前要多一个步骤,在执行java com.saleson.jdk.Demo之前,先使用javac 命令编译java文件
在这里插入图片描述
Working directory改为跟class的输出目录。

添加compile java tool
在这里插入图片描述

FieldContentDescribe
Program{openjdk}/build/macosx-x86_64-normal-server-slowdebug/jdk/bin/javac编译openjdk后的javac命令
Arguments-d /Users/saleson/Desktop/jdkdebug /Users/saleson/IdeaProjects/personal/src/main/java/com/saleson/jdk/Demo.java-d class输出目录, 后面跟着java文件路径

运行之后跟调试class是一样。

调试jar

仍以com.saleson.jdk.Demo为例,先使用maven编译jar包。在项目的 pom.xml中添加maven-plugin

<build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>com.saleson.jdk.Demo</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>assembly</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

在java工程根目录中执行mvn命令

$ mvn -DskipTests assembly:assembly
....
NOTE: If multiple descriptors or descriptor-formats are provided for this project, the value of this file will be non-deterministic!
[WARNING] Replacing pre-existing project main-artifact file: /Users/saleson/IdeaProjects/personal/target/personal-1.0-SNAPSHOT.jar
with assembly file: /Users/saleson/IdeaProjects/personal/target/personal-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.539 s
[INFO] Finished at: 2022-04-01T14:05:06+08:00
[INFO] Final Memory: 14M/47M
[INFO] ------------------------------------------------------------------------

新建运行jar包的Custom Build Application
在这里插入图片描述

FieldContentDescribe
Target选择前面创建好的Custom Build Target
Executable{openjdk}/build/macosx-x86_64-normal-server-slowdebug/jdk/bin/java选择编译后的openjdk目录下的java命令
Propram arguments-jar personal-1.0-SNAPSHOT.jarjava 命令后面跟着的参数
Working directory/Users/saleson/IdeaProjects/personal/targetjar所在的目录

运行后效果与前两种调试效果是一样的。

参考

https://segmentfault.com/a/1190000040305260
https://www.jianshu.com/p/ee7e9176632c
https://blog.youkuaiyun.com/qq_33543634/article/details/121187405
https://www.it1352.com/1570784.html
https://www.cnblogs.com/maxiaofang/p/6254392.html
https://blog.youkuaiyun.com/tiankong_12345/article/details/104088500
https://www.jianshu.com/p/0fc877be4c3d
https://blog.youkuaiyun.com/u012667477/article/details/119842942

### 准备工作 为了在 Mac 上使用 CLion 调试 OpenJDK,需要先安装 Bootstrap JDK 和必要的开发工具。由于编译过程中会涉及到 C++ 编写的部分组件以及 Java 编写的部分组件,因此建议下载并安装一个合适的 Bootstrap JDK 版本[^1]。 对于 MacOS 用户来说,推荐选择适合该操作系统的 OpenJDK 11 或者更早一点的稳定版本作为 Bootstrap JDK 来支持后续的编译过程。可以从官方网站获取适用于 macOS 的 OpenJDK 安装包,并按照指引完成安装。 ### 获取 OpenJDK 源码 接着应当从 GitHub 等平台克隆最新的 OpenJDK 源代码仓库至本地环境。如果希望简化配置流程,则可以考虑基于已有的项目模板,比如 `xiaodaojava` 提供了一个带有预设好的 CMakeLists.txt 文件用于辅助构建和调试的工作流[^2]。 ```bash git clone https://github.com/xiaodaojava/openjkd11-CmakeList.git cd openjkd11-CmakeList ``` ### 配置 CLion 工程 打开 CLion 后加载上述克隆下来的工程目录,在此之前可能还需要执行一些额外命令来生成 IDE 所需的支持文件以便更好地解析源码结构: 进入 jdk 源码根目录下运行如下指令以创建 compile_commands.json 文件,这有助于提高索引效率和支持更多特性如自动补全等功能[^3]: ```bash make compile-commands ``` 此时应该可以在 CLion 中看到完整的 OpenJDK 源码树形视图了。 ### 设置断点与启动调试器 当一切准备就绪之后便可在感兴趣的函数处设置断点了;随后点击右上角绿色三角按钮旁边的齿轮图标选择 “Edit Configurations...”,在这里添加一个新的应用程序配置项并将 Main Class 字段留空(因为我们不是要直接跑某个特定程序而是想要附加到 JVM 进程),最后记得勾选 Enable attaching to process by PID 复选项允许连接外部进程。 一旦完成了以上步骤,就可以通过菜单栏中的 Run -> Attach to Process ... 寻找目标 java.exe (macOS 下可能是 javaw) 实例来进行实时跟踪分析了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值