为了验证前面几篇文章的正确性,可以编译OpenJDK的Hotspot虚拟机然后进行调试验证。
编译虚拟机
本文在CentOS 7上编译OpenJDK的Hotspot虚拟机:
- 首先安装必备的库,命令如下;
sudo yum -y install freetype libXtst-devel libXt-devel libXrender-devel cups-devel freetype-devel alsa-lib-devel
- 然后运行openjdk目录中的配置脚本;
./configure --with-debug-level=slowdebug --enable-debug-symbols ZIP_DEBUGINFO_FILES=0
- 最后运行make命令编译。
make all CONF=linux-x86_64-normal-server-slowdebug ZIP_DEBUGINFO_FILES=0
上述编译成功后,编译输出的文件均保存在子目录build/linux-x86_64-normal-server-slowdebug中,该目录的层次结构如下所示,其中带debuginfo的即为调试过程中将用到的符号信息。
~/openjdk8/build/linux-x86_64-normal-server-slowdebug
|- hotspot
| |- dist
| |- linux_amd64_docs
| |- linux_amd64_compiler2
| | |- debug
| | | |- libjvm.so
| | | |- ...
| | |- fastdebug
| | |- ...
|- jdk
| |- bin
| | |- jar
| | |- jar.debuginfo
| | |- java
| | |- javac
| | |- javac.debuginfo
| | |- ...
| |- lib
| | |- amd64
| | | |- jvm.cfg
| | | |- server
| | | | |- libjvm.so
| | | | |- libjvm.debuginfo
| | | | |- Xusage.txt
| | | |- libjava.so
| | | |- libjava.debuginfo
| | | |- libnio.so
| | | |- libnio.debuginfo
| | | |- ...
| | |- ext
| | |- ...
| |- include
|- ...
调试虚拟机
以下终端交互过程展示了调试虚拟机的基本操作:
[suntao@CentOS-VM openjdk8]$ cd build/linux-x86_64-normal-server-slowdebug/jdk/bin/
[suntao@CentOS-VM bin]$ gdb java
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/suntao/openjdk8/build/linux-x86_64-normal-server-slowdebug/jdk/bin/java...done.
(gdb) b /home/suntao/openjdk8/jdk/src/solaris/bin/java_md_solinux.c:485
No source file named /home/suntao/openjdk8/jdk/src/solaris/bin/java_md_solinux.c.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (/home/suntao/openjdk8/jdk/src/solaris/bin/java_md_solinux.c:485) pending.
(gdb) r -version
Starting program: /home/suntao/openjdk8/build/linux-x86_64-normal-server-slowdebug/jdk/bin/java -version
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Breakpoint 1, CreateExecutionEnvironment (pargc=0x7fffffffb2ec, pargv=0x7fffffffb2e0,
jrepath=0x7fffffffc350 "/home/suntao/openjdk8/build/linux-x86_64-normal-server-slowdebug/jdk", so_jrepath=4096,
jvmpath=0x7fffffffb350 "/home/suntao/openjdk8/build/linux-x86_64-normal-server-slowdebug/jdk/lib/amd64/server/libjvm.so", so_jvmpath=4096,
jvmcfg=0x7fffffffd350 "/home/suntao/openjdk8/build/linux-x86_64-normal-server-slowdebug/jdk/lib/amd64/jvm.cfg", so_jvmcfg=4096)
at /home/suntao/openjdk8/jdk/src/solaris/bin/java_md_solinux.c:485
485 mustsetenv = RequiresSetenv(wanted, jvmpath);
Missing separate debuginfos, use: debuginfo-install glibc-2.17-260.el7.x86_64
(gdb) c
Continuing.
[New Thread 0x7ffff7feb700 (LWP 44444)]
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff7feb700 (LWP 44444)]
0x00007fffe10002b4 in ?? ()
Missing separate debuginfos, use: debuginfo-install libgcc-4.8.5-36.el7.x86_64 libstdc++-4.8.5-36.el7.x86_64
(gdb) c
Continuing.
[New Thread 0x7ffff4473700 (LWP 44445)]
[New Thread 0x7ffff4372700 (LWP 44446)]
[New Thread 0x7fffde07b700 (LWP 44447)]
[New Thread 0x7fffddf7a700 (LWP 44448)]
[New Thread 0x7fffdde79700 (LWP 44449)]
[New Thread 0x7fffddd78700 (LWP 44450)]
[New Thread 0x7fffddc77700 (LWP 44451)]
[New Thread 0x7fffddb76700 (LWP 44452)]
[New Thread 0x7fffdda75700 (LWP 44453)]
[New Thread 0x7fffdd974700 (LWP 44454)]
openjdk version "1.8.0-internal-debug"
OpenJDK Runtime Environment (build 1.8.0-internal-debug-suntao_2019_03_14_23_25-b00)
OpenJDK 64-Bit Server VM (build 25.71-b00-debug, mixed mode)
[Thread 0x7fffdd974700 (LWP 44454) exited]
[Thread 0x7fffddd78700 (LWP 44450) exited]
[Thread 0x7fffde07b700 (LWP 44447) exited]
[Thread 0x7fffddb76700 (LWP 44452) exited]
[Thread 0x7fffddc77700 (LWP 44451) exited]
[Thread 0x7fffdde79700 (LWP 44449) exited]
[Thread 0x7fffddf7a700 (LWP 44448) exited]
[Thread 0x7ffff4372700 (LWP 44446) exited]
[Thread 0x7ffff4473700 (LWP 44445) exited]
[Thread 0x7ffff7feb700 (LWP 44444) exited]
[Thread 0x7ffff7fec740 (LWP 44440) exited]
[Inferior 1 (process 44440) exited normally]
(gdb)
- 首先进入编译生成的jdk目录,运行生成的java命令而不是先前安装的java;
- 将断点设置在文件java_md_solinux.c中的CreateExecutionEnvironment函数中,从断点输出可以检查加载的JVM动态库是否是编译生成的库;
- 程序在断点暂停时输出
jvmpath=0x7fffffffb350 "/home/suntao/openjdk8/build/linux-x86_64-normal-server-slowdebug/jdk/lib/amd64/server/libjvm.so"
,这正是编译生成的JVM。
网友评论