Java深入计划-JVM篇第一章
操作环境
系统: Deepin20.4
源码: OpenJDK12
调试工具: Clion 2019.1.4
(当前系统平台编译的OpenJDK只能在相同的系统平台进行调试)
第一步: OpenJDK12 源码获取
方式①: 通过Mercurial代码版本管理工具从Repository中直接取得源码.
Repository地址: https://hg.openjdk.java.net/jdk/jdk12
方式②: 访问 JDK 版本的仓库页面,然后点击左侧菜单中的 Browse
(如下图),点击后将显示源码根目录页面.再点击点击左边的zip
即可下载当前版本的源码。
(
linux方式:
wget -c https://hg.openjdk.java.net/jdk/jdk12/archive/06222165c35f.zip
第二步: 构建编译环境
- 安装
Bootstrap JDK
因为OpenJDK
由多个部分构成:HotSpot
、JDK 类库
、JAXWS
、JAXP
等, 其中HotSpot
代码使用 C、C++ 编写, 而更多的代码是使用 Java 语言实现, 因此编译这些 Java 代码就需要用到另一个编译期可用的 JDK, 官方成这个 JDK 为 Bootstrap JDK。编译 OpenJDK 12 时,Bootstrap JDK
就须使用待编译 JDK 版本n-1或之后的版本。
sudo apt-get install openjdk-11-jdk
- 安装编译器
GCC
!!! 注意: 由于系统的不同, 安装的GCC版本可能不一样, Deepin系统安装的GCC
版本: 8.3.0
sudo apt-get install build-essential
- 安装编译
OpenJDK
的依赖项
工具 | 库名称 | 安装命令 |
---|---|---|
FreeType | The FreeType Project | sudo apt-get install libfreetyped-dev |
CUPS | Common UNIX Printing System | sudo apt-get install libcups2-dev |
X11 | X window System | sudo apt-get install libx11-dev libxext-dev libxrender-dev libxrandr-dev libxtst-dev libxt-dev |
ALSA | Advance Linux Sound Architecture | sudo apt-get install libasound2-dev |
libffi | Portable Foregin Function Interface Library | sudo apt-get install libffi-dev |
Autoconf | Executable Package of M4 Macros | sudo apt-get install autoconf |
- 其他依赖项
sudo apt-get install libfontconfig1-dev
sudo apt-get install gobjc
(gcc让支持cc1obj, 用于Clion导入时使用)
第三步: 编译
- 解压
jdk12-06222165c35f.zip
unzip jdk12-06222165c35f.zip
- 修改目录权限(Clion导入需要目录权限)
sudo chmod -R 777 jdk12-06222165c35f
- 进入源码目录,执行
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
命令即可.
- 执行
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”命令清理目录,才能确保新的配置生效
- 验证
执行: 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, 阅读不友好)
-
官网下载
liunx
版本Clion
,启动后会自动配置工具链
-
CLion
选择New CMake Project from Sources
, 在源码文件夹中填入OpenJDK源码
根目录,此时,CLion已经自动选择好了需要导入的源码,如图所示。点击OK按钮就会导入源码并自动创建好CMakeLists.txt文件。
!!! 注意: 有人点击OK
按钮时可能出现提示: Cannot create CMake project
(如图), 这是由于没有操作OpenJDK源码
目录以及子目录权限, 需要目录权限: sudo chmod -R 777 jdk12-06222165c35f
. 如果还是无法导入, 把Clion
目录权限也修改为777.
- 在
Run/Debug Configurations
中增加一个CMake Applcatio
, 然后在Executable
选择刚才编译出来的FastDebug
目录下的java
命令, 运行参数加上-version
, 再把Before launch
里面的Build
去掉,就完成配置了.HotSpot
虚拟机启动器的执行入口是java.c
的JavaMain()
方法,可以打断点单步跟踪,完成调试,相关截图如下。(如果断点调试期间出现connection timeout, 原因同上:Clion
目录和OpenJDK源码
目录没有操作权限)
第五步:Debug
普通Java
程序
- 创建一个普通的
Java类
文件:Test.java
public class Test {
public static void main(String[] args) {
System.out.println("hello jvm");
}
}
- 用第四步编译好的
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
-
Clion: 在
Run/Debug Configurations
中增加一个CMake Applcatio
,相关参数如图
-
调试结果
!
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
- 完成第一到三步后, 在
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`
-
Clion导入
OpenJDK
- Clion >>>
Open
>>>选择文件
>>>${source_root}/build/linux-x86_64-server-fastdebug
>>>compile_commands.json
- Clion >>>
Tools
->Compilation Database
->Change Project Root
功能,选中JDK源码
目录
- Clion >>>
File
>>>Setting
>>>Custom Build Targets
创建
make linux-x86_64-server-fastdebug
和clean linux-x86_64-server-fastdebug
- 配置Run/Debug configurations, 创建==Custom Build Application类型==启动配置
Executable:
${source_root}/build/linux-x86_64-server-fastdebug/jdk/bin/java
-
删除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:
-
完成调试
- Clion >>>
-
当前导入方式
Debug
普通Java程序: 参考第五步.
其他
关于调试过程中控制台出现: Signal: SIGSEGV (Segmentation fault)
IGSEGV代表指针所对应的地址是无效地址,没有物理内存对应该地址。其实还有一个,是SIGBUS,代表指针所对应的地址是有效地址,但总线不能正常使用该指针,通常是未对齐的数据访问所致。
解决方案①(参考):
- touch ~/.gdbinit (在
gdb
>>> 执行show environment HOME
, 会发现gdb默认配置目录是在~下,如图)- 在.gdbinit文件中添加
handle SIGSEGV pass noprint nostop
handle SIGUSR1 pass noprint nostop
handle SIGUSR2 pass noprint nostop
set logging on
解决方案②:
编译slowdebug级别的OpenJDK
附:
安装gdb:
apt-get install gdb # 非必须gdb,Clion默认的gdb配置目录和主动安装的gdb一致
Clion工具链选择自己安装的gdb # 非必须
评论区