JVM-在Visual Studio Code中调试OpenJDK8

写在前面

上次在MacOS系统下编译并调试OpenJDK12后,觉得现在在日常开发中都使用的JDK8,所以就还是想主要学习OpenJDK8的源码,然后就又萌发了调试OpenJDK8源码的方式。

根据之前编译调试OpenJDk12的文章(点击查看),首先想到的也是使用CLion来调试,但是,很遗憾,OpenJDK8不支持compilation database,所以只有换一种方法。

查询资料的过程中,发现R大在知乎说,他一般采用VIM的方式进行开发,所以我也开始找相关资料,配置各种插件,最后,放弃了。因为VIM确实学习成本过高,可能等把VIM整明白了,就已经没有学JVM的欲望了。

后来,又瞄上了Visual Studio Code,因为之前也用它写Python,也知道它可以比较方便的安装各种插件来支持不同语言的开发工作,而且目前也有很多工程师用它写C/C++代码,所以最后,通过一系列探索,终于在Visual Studio Code,配置好了调试OpenJDK8的环境。


关于编译OpenJDK8

MacOS编译OpenJDK8的文章,网上很多,多查几篇文章,基本都可以搞定,所以本文重点在怎么在Visual Studio Code调试,而不是编译。

可以通过以下关键字Google一下:MacOS Cataline OpenJDK8,顺便也推荐一下,当时我所参考的博客:

一定要在编译成功后,在操作后续步骤哦,否则就是在浪费时间~


插件安装

Visual Studio Code安装两个插件就可以,具体如下:

  • C/C++:为Visual Studio Code添加C/C++支持;
  • CodeLLDB:调试工具,因为在实际调试的时候,只使用C/C++提供的Debug功能,在调试过程中,会卡住,程序不继续执行,具体原因不知道为什么,所以我使用这个插件进行调试。

配置

c_cpp_properties.json

Command + Shift+ P,选择C/C++: Edit Configurations (JSON),会自动创建c_cpp_properties.json文件,我的配置文件如下:

{
    "configurations": [
        {
            "name": "Mac",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/local/include",
                "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1",
                "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.3/include",
                "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include",
                "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
                "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks"
            ],
            "defines": [],
            "macFrameworkPath": [
                "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks"
            ],
            "compilerPath": "/usr/bin/clang",
            "cStandard": "c11",
            "cppStandard": "gnu++14",
            "intelliSenseMode": "clang-x64"
        }
    ],
    "version": 4
}

settings.json

这个文件,我的配置是主要将源码报红的部分给隐藏,代码检查的报错并不影响源码的编译与调试,我对这些代码检查的理解是,目前新版本的C/C++可能不支持某些语法或者某些语法已经过时,还有可能是Java虚拟机是跨平台的,所以我觉得它所引用的一些类库什么的可能是别的系统才有的。当然,这只是我的猜测,我的目的是调试OpenJDK8的代码,而不是去找这些问题,所以我直接关闭了代码检查时的错误提示。

具体路径:Preferences->Settings下,按照下图进行设置:

settings.json

设置完毕后,应该就可以在项目根目录下,.vscode目录下看到settings.json文件,我的settings.json文件如下:

{
  "git.ignoreLimitWarning": true,
  "files.associations": {
    "random": "cpp",
    "*.tcc": "cpp"
  },
  "C_Cpp.errorSquiggles": "Disabled",
}

tasks.json

tasks.json文件,可以配置一些编译的相关任务,可以通过Command + Shift + B生成该文件。

我在这边配置了makeclean相关的任务。

下面是我的tasks.json文件,字段配置可参考官方的文档,解释很详细,就不在这里赘述:

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "label": "openjdk8 slowdebug build",
      "type": "shell",
      "command": "make",
      "args": [
        "CONF=openjdk8-server-64-slowdebug-vscode",
        "COMPILER_WARNINGS_FATAL=false"
      ],
      "problemMatcher": [],
      "group": {
        "kind": "build",
        "isDefault": true
      }
    }, {
      "label": "openjdk8 slowdebug clean",
      "type": "shell",
      "command": "make",
      "args": [
        "CONF=openjdk8-server-64-slowdebug-vscode",
        "clean"
      ],
      "group": {
        "kind": "build",
        "isDefault": true
      }
    }
  ]
}

配置完成后,可以通过Command + Shift + B快捷键执行配置的任务。


launch.json

在源码根目录.vscode目录下的launch.json文件,用来配置执行参数,比如你想执行java -version或者使用java来运行一个javaclass文件,都需要通过该文件来配置。

下面是我的相关配置:

{
  // 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": "java -version[CodeLLDB]",
      "type": "lldb",
      "request": "launch",
      "program": "${workspaceFolder}/build/openjdk8-server-64-fastdebug-vscode/jdk/bin/java",
      "args": [
        "-version"
      ],
      "cwd": "${workspaceFolder}",
      "preRunCommands": [
        "breakpoint set --file ${workspaceFolder}/jdk/src/share/bin/main.c --line 125 -C 'pro hand -p true -s false SIGSEGV SIGBUS' --auto-continue true"
      ],
      "preLaunchTask": "openjdk8 slowdebug build"
    }, {
      "name": "HeapOOM",
      "type": "lldb",
      "request": "launch",
      "program": "${workspaceFolder}/build/openjdk8-server-64-fastdebug-vscode/jdk/bin/java",
      "args": [
        "-XX:+UseG1GC",
        "-Xms20m",
        "-Xmx20m",
        "-classpath",
        "/Users/howieli/Work/JDK/java-source",
        "HeapOOM"
      ],
      "cwd": "${workspaceFolder}",
      "stopOnEntry": false,
      "preRunCommands": [
        "breakpoint set --file ${workspaceFolder}/jdk/src/share/bin/main.c --line 125 -C 'pro hand -p true -s false SIGSEGV SIGBUS' --auto-continue true"
      ],
      "preLaunchTask": "openjdk8 slowdebug build"
    }
  ]
}

配置中,我觉得大部分都是很清晰的,对具体参数不了解的同学,可以自行使用搜索引擎,这里我主要说下四个参数:

  1. type:这里使用lldb,而不是cppdbgcppdbg类型,是使用的官方插件中的Debug工具,而lldb是使用前面安装的CodeLLDB插件提供的Debug工具;

  2. args:配置参数,这个参数看起来没什么好说的,但却容易踩坑,所以着重提醒一下,这里的参数一定要一个一个的配置,之前我配置成下面这样,看上去没问题,但却怎么都无法正常执行;

    [
      "-XX:+UseG1GC -Xms20m -Xmx20m",
      "-classpath /Users/howieli/Work/JDK/java-source",
      "HeapOOM"
    ]
  3. preRunCommands:这里是为了调试启动时自动忽略SIGSEGVSIGBUS的错误提示,否则无法顺利调试,具体原因可以查看JVM-在MacOS系统上使用CLion编译并调试OpenJDK12

  4. preLaunchTask:运行前执行一个任务,这里所配置的值要和tasks.json中某个任务的label对应。这里配置的是在运行该程序前,首先执行make,也就是编译JDK的命令,再开始运行。

调试

我在这边选择运行一个Java的小程序(HeapOOM),简单的打个端点:

调试准备

点击启动按钮,就可以开始调试啦。

调试


写在最后

以上就是我折腾的一些经验,可能不是最完美的,但基本满足了我的目标,如果有错误,麻烦提出,共同进步,如果有更好的调试经验,也欢迎大佬一起交流,谢谢。


参考资料


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!