Windows10下vs2010单步调试jvm

缘起

【1】中我们已经在win10环境下编译了openjdk8, 下面就开始单步调试hotspot.

分析

关于jdk、jre、jvm 、Hotspot之间的联系和区别参见【2】

首先看看openjdk的源码包结构

1
2
3
4
5
6
7
8
9
10
openjdk 
—— corba:不流行的多语言、分布式通讯接口
—— hotspot:Java 虚拟机
—— jaxp:XML 处理
—— jaxws:一组 XML web services 的 Java API
—— jdk:java 开发工具包
—— —— 针对操作系统的部分
—— —— share:与平台无关的实现
—— langtools:Java 语言工具
—— nashorn:JVM 上的 JavaScript 运行时

我们熟知的java的一些类就在D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\jdk\src\share\classes中,例如java.util工具包

但是我们要看的其实并不是这些. 我们要看的是hotspot. 即D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\hotspot 目录下

因为我们要做的事情是,使用hotspot执行一个class字节码文件. 我们关注的是这样一个过程. 而不是一个java源文件编译成class文件. 这里面具体的关系若有不清楚,参看【2】.

hotspot源码包路径是D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\hotspot

解释如下

好像最新的源码结构中没有src\share\tools\launcher

【1】中我们最后编译出来了java.exe 在

D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\build\windows-x86_64-normal-server-fastdebug\jdk\objs\java_objs 目录中有.

然后我们理解一下java.exe和虚拟机(即这里的hotspot)之间的关系.

hotspot是作为动态链接库(dll)的形式被 java.exe 载入的。java.exe 负责解析參数,载入虚拟机链接库,它须要调用虚拟机中的函数来完毕运行 Java 程序的功能。所以,你在HotSpot的源码中找不到启动的程序的 main 函数.

好了,言归正传,我们开始debug我们的hotspot源码.

创建hotspot的vs2010工程

  1. cmd执行 D:\vs2010\VC\bin\amd64\vcvars64.bat,但是执行完毕此命令之后不要关闭cmd窗口,因为这里仅仅是修改了环境变量

  2. 编辑D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\hotspot\make\windows\create.bat

    修改142行为cygwin64的安装目录如下(依据你自己的cygwin64的安装目录进行修改)

    1
    if exist d:\cygwin64\bin set HOTSPOTMKSHOME=d:\cygwin64\bin
  3. 执行下面命令

    1
    2
    3
    cd D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\hotspot\make\windows
    之后
    create.bat D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\jdk

    执行完毕之后,在D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\hotspot\build中多了vs-amd64目录,里面就有了一个vs2010工程. 这个就是hotspot源码工程.

  4. D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\build\windows-x86_64-normal-server-fastdebug\jdk\bin 下找到java.diz,用WinRAR解压它,将解压出的java.pdb和java.map放进同级目录,也就是D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\build\windows-x86_64-normal-server-fastdebug\jdk\bin 中. 这一步是为了调试同级目录下的java.exe

利用VS2010单步调试

  1. vs2010打开 D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\hotspot\build\vs-amd64\jvm.vcxproj

  2. 配置编译参数Compiler2 Fastdebug + X64

  3. 右键项目点击Properties. 选择Debugging之后配置如下三个参数

    具体为

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Command为编译好的java.exe路径 

    D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\build\windows-x86_64-normal-server-fastdebug\jdk\bin\java.exe

    Environment 为编译好的jdk路径

    JAVA_HOME=D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\build\windows-x86_64-normal-server-fastdebug\jdk

    Command Arguments为jvm参数

    -XXaltjvm=$(TargetDir) -Dsun.java.launcher=gamma -Djava.class.path=D:\openjdk-8u40-src-b25-10_feb_2015\javacode Test

为了便于调试,准备一个Test.java 放进创建的路径D:\openjdk-8u40-src-b25-10_feb_2015\javacode,下面编写一个Test.java

1
2
3
4
5
6
7
public class Test {

public static void main(String[] args) {
System.out.println("hello world");
}

}

然后打开cmd,使用D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\build\windows-x86_64-normal-server-fastdebug\jdk\bin\javac.exe 对其进行编译得到Test.class.

注意上面配置的XXaltjvm参数中就有这个Test,其中我们使用了 -Djava.class.path 来指定class文件位置

添加断点 share\vm\runtime\thread.cpp,line 3305, create_vm

点击下面的按钮

于是就可以结合源码来学习jvm内部原理了.

参考

【1】https://yfsyfs.github.io/2019/07/11/Windows10%E4%B8%8B%E7%BC%96%E8%AF%91openjdk8/

【2】https://yfsyfs.github.io/2019/07/13/JDK-JRE-JVM-HotSpot-%E4%B9%8B%E9%97%B4%E7%9A%84%E5%8C%BA%E5%88%AB%E5%92%8C%E8%81%94%E7%B3%BB/#more