侧边栏壁纸
博主头像
Curllen博主等级

早上的云霞好美~

  • 累计撰写 12 篇文章
  • 累计创建 18 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

深入理解Java虚拟机(一):Deepin构建OpenJDK12编译环境并调试

Curllen
2022-02-25 / 0 评论 / 0 点赞 / 1,671 阅读 / 5,731 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-02-25,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

Java深入计划-JVM篇第一章

操作环境

系统: Deepin20.4
源码: OpenJDK12
调试工具: Clion 2019.1.4
(当前系统平台编译的OpenJDK只能在相同的系统平台进行调试)

第一步: OpenJDK12 源码获取

方式①: 通过Mercurial代码版本管理工具从Repository中直接取得源码.

Repository地址: https://hg.openjdk.java.net/jdk/jdk12

方式②: 访问 JDK 版本的仓库页面,然后点击左侧菜单中的 Browse(如下图),点击后将显示源码根目录页面.再点击点击左边的zip即可下载当前版本的源码。
(image.png

linux方式: wget -c https://hg.openjdk.java.net/jdk/jdk12/archive/06222165c35f.zip

第二步: 构建编译环境

  1. 安装Bootstrap JDK

    因为 OpenJDK 由多个部分构成: HotSpotJDK 类库JAXWSJAXP 等, 其中 HotSpot 代码使用 C、C++ 编写, 而更多的代码是使用 Java 语言实现, 因此编译这些 Java 代码就需要用到另一个编译期可用的 JDK, 官方成这个 JDK 为 Bootstrap JDK。编译 OpenJDK 12 时,Bootstrap JDK 就须使用待编译 JDK 版本n-1或之后的版本。

sudo apt-get install openjdk-11-jdk

  1. 安装编译器GCC

    !!! 注意: 由于系统的不同, 安装的GCC版本可能不一样, Deepin系统安装的GCC版本: 8.3.0

sudo apt-get install build-essential

  1. 安装编译OpenJDK的依赖项
工具库名称安装命令
FreeTypeThe FreeType Projectsudo apt-get install libfreetyped-dev
CUPSCommon UNIX Printing Systemsudo apt-get install libcups2-dev
X11X window Systemsudo apt-get install libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev
ALSAAdvance Linux Sound Architecturesudo apt-get install libasound2-dev
libffiPortable Foregin Function Interface Librarysudo apt-get install libffi-dev
AutoconfExecutable Package of M4 Macrossudo apt-get install autoconf
  1. 其他依赖项

sudo apt-get install libfontconfig1-dev

sudo apt-get install gobjc (gcc让支持cc1obj, 用于Clion导入时使用)

第三步: 编译

  1. 解压jdk12-06222165c35f.zip

unzip jdk12-06222165c35f.zip

  1. 修改目录权限(Clion导入需要目录权限)

sudo chmod -R 777 jdk12-06222165c35f

  1. 进入源码目录,执行configure命令

    GCC在8.0之后的版本加入了stringop truncation的验证警告, 如果直接执行bash configure --enable-debug --with-jvm-variants=server会因为 出现警告导致编译不通过, 需要禁止掉警告再进行编译, 否者会出现如下报错:

    error: ‘char* __builtin_strncpy(char*, const char*, long unsigned int)’ output truncated before terminating nul copying as many bytes from a string as its length

GCC版本 > 8.0: bash configure --disable-warnings-as-errors --enable-debug --with-jvm-variants=server

GCC版本 < 8.0: bash configure --enable-debug --with-jvm-variants=server

此时如果出现依赖缺失, 会给出提示, 根据提示执行安装命令后再次执行configure命令即可.

  1. 执行make images
    编译成功后,会在 jdk源码目录>build目录生成配置名称目录(如linux-x86_64-server-fastdebug), 该目录下结构:
buildtools/:用于生成、存放编译过程中用到的工具
hotspot/:HotSpot 虚拟机编译的中间文件
images/:使用 make *-image 产生的镜像存放在这里
jdk/:编译后产生的 jdk 就放在这里
support/:存放编译时产生的中间文件
test-results/:存放编译后的自动化测试结果
configure-support/:这三个目录是存放执行 configure、make 和 test 的临时文件
make-support/
test-support/

如果需要多次编译,或者目录结构成功产生后又再次修改了配置,必须先使用“make clean”和“make dist-clean”命令清理目录,才能确保新的配置生效

  1. 验证
执行: cd build/linux-x86_64-server-fastdebug/jdk/bin/
执行: ./java -version
结果:
openjdk version "12-internal" 2019-03-19
OpenJDK Runtime Environment (fastdebug build 12-internal+0-adhoc.Curllen.jdk12)
OpenJDK 64-Bit Server VM (fastdebug build 12-internal+0-adhoc.Curllen.jdk12, mixed mode)

第四步: Clion导入并调试JVM(自动生成CMakeLists.txt, 阅读不友好)

  1. 官网下载liunx版本Clion,启动后会自动配置工具链
    image.png

  2. CLion选择New CMake Project from Sources, 在源码文件夹中填入OpenJDK源码根目录,此时,CLion已经自动选择好了需要导入的源码,如图所示。点击OK按钮就会导入源码并自动创建好CMakeLists.txt文件。
    image.png
    image.png

!!! 注意: 有人点击OK按钮时可能出现提示: Cannot create CMake project(如图), 这是由于没有操作OpenJDK源码目录以及子目录权限, 需要目录权限: sudo chmod -R 777 jdk12-06222165c35f. 如果还是无法导入, 把Clion目录权限也修改为777.
image.png

  1. Run/Debug Configurations中增加一个CMake Applcatio, 然后在Executable选择刚才编译出来的FastDebug目录下的java命令, 运行参数加上-version, 再把Before launch里面的Build去掉,就完成配置了. HotSpot虚拟机启动器的执行入口是java.cJavaMain()方法,可以打断点单步跟踪,完成调试,相关截图如下。(如果断点调试期间出现connection timeout, 原因同上: Clion目录和OpenJDK源码目录没有操作权限)
    image.png
    image.png
    image.png
    第五步: Debug普通Java程序

  1. 创建一个普通的Java类文件: Test.java
public class Test {

    public static void main(String[] args) {
        System.out.println("hello jvm");
    }
}
  1. 用第四步编译好的jdk编译Test.java
Curllen@Curllen-PC:~/Learn/java_code$ /home/Curllen/Learn/jdk12/build/linux-x86_64-server-fastdebug/jdk/bin/./javac Test.java 
Curllen@Curllen-PC:~/Learn/java_code$ ls
Test.class  Test.java
  1. Clion: 在Run/Debug Configurations中增加一个CMake Applcatio,相关参数如图
    image.png

  2. 调试结果
    image.png!

Clion另外一种调试JVM方式(open a project by loading its compilation database,加载编译数据库方式来打开项目, 阅读友好)

参考链接: https://blog.jetbrains.com/clion/2020/03/openjdk-with-clion/

If you are working with a project which is not based on CMake, Gradle, or Makefiles, you can still benefit from the advanced IDE features that CLion provides. One way is to import a non-CMake project and let CLion convert it into a simple CMake structure. Another option is to open a project by loading its compilation database

  1. 完成第一到三步后, 在JDK源码目录执行make compile-commands,在${source_root}/build/linux-x86_64-server-fastdebug下生成compile_commands.json文件,注: ${source_root} 代指JDK源码目录.
Curllen@Curllen-PC:~/Desktop$ cd /home/Curllen/Learn/jdk12/
Curllen@Curllen-PC:~/Learn/jdk12$ make compile-commands
Building target 'compile-commands' in configuration 'linux-x86_64-server-fastdebug'
……

注: 如果不想使用编译好的penJDK: linux-x86_64-server-fastdebug, 则可以新编译一个新的OpenJDK,如想编译一个slowdebug级别的OpenJDK.

bash configure --with-debug-level=slowdebug --with-jvm-variants=server # 执行config
make CONF=linux-x86_64-server-fastdebug images # 指定配置创建image
make CONF=linux-x86_64-server-fastdebug compile-commands # 指定配置创建`compile_commands.json`
  1. Clion导入OpenJDK

    • Clion >>> Open >>> 选择文件 >>> ${source_root}/build/linux-x86_64-server-fastdebug >>> compile_commands.json
      image.png
      image.png
    • Clion >>> Tools -> Compilation Database -> Change Project Root功能,选中JDK源码目录
      image.png
      image.png
    • Clion >>> File >>> Setting >>> Custom Build Targets
      image.png

    创建 make linux-x86_64-server-fastdebugclean linux-x86_64-server-fastdebug

    image.png
    image.png
    image.png

    • 配置Run/Debug configurations, 创建==Custom Build Application类型==启动配置

    Executable: ${source_root}/build/linux-x86_64-server-fastdebug/jdk/bin/java

    image.png
    image.png
    image.png

    • 删除Build:The JDK build system is smart, and incremental compilation is pretty fast. However, if you don’t want to rebuild OpenJDK before each run or debug, you can disable build step in the Before launch section of the run configuration settings:
      image.png

    • 完成调试
      image.png

  2. 当前导入方式Debug普通Java程序: 参考第五步.

其他

关于调试过程中控制台出现: Signal: SIGSEGV (Segmentation fault)

IGSEGV代表指针所对应的地址是无效地址,没有物理内存对应该地址。其实还有一个,是SIGBUS,代表指针所对应的地址是有效地址,但总线不能正常使用该指针,通常是未对齐的数据访问所致。

解决方案①(参考):

  1. touch ~/.gdbinit (在gdb >>> 执行 show environment HOME, 会发现gdb默认配置目录是在~下,如图)
  2. 在.gdbinit文件中添加
handle SIGSEGV pass noprint nostop
handle SIGUSR1 pass noprint nostop
handle SIGUSR2 pass noprint nostop
set logging on

image.png

解决方案②:

编译slowdebug级别的OpenJDK

附:

安装gdb: apt-get install gdb # 非必须gdb,Clion默认的gdb配置目录和主动安装的gdb一致

Clion工具链选择自己安装的gdb # 非必须
image.png

0

评论区