将已经编译好的openjdk1.8代码,使用VS2010来调试,研究JVM启动过程以及原理。
目录结构
openjdk源码组织结构
HotSpot源码包结构
创建hotspot VS2010工程
利用VS2010单步调试
具体的openjdk编译过程可以参考 https://blog.csdn.net/u014106644/article/details/89316483
首先研究一下openjdk代码的组织结构
openjdk
—— corba:不流行的多语言、分布式通讯接口
—— hotspot:Java 虚拟机
—— jaxp:XML 处理
—— jaxws:一组 XML web services 的 Java API
—— jdk:java 开发工具包
—— —— 针对操作系统的部分
—— —— share:与平台无关的实现
—— langtools:Java 语言工具
—— nashorn:JVM 上的 JavaScript 运行时
hotspot包即为常说的java虚拟机hotspot源码包路径
具体的源码结构如下
├─agent Serviceability Agent的客户端实现
├─make 用来build出HotSpot的各种配置文件
├─src HotSpot VM的源代码
│ ├─cpu CPU相关代码(汇编器、模板解释器、ad文件、部分runtime函数在这里实现)
│ ├─os 操作系相关代码
│ ├─os_cpu 操作系统+CPU的组合相关的代码
│ └─share 平台无关的共通代码
│ ├─tools 工具
│ │ ├─hsdis 反汇编插件
│ │ ├─IdealGraphVisualizer 将server编译器的中间代码可视化的工具
│ │ ├─launcher 启动程序“java”
│ │ ├─LogCompilation 将-XX:+LogCompilation输出的日志(hotspot.log)整理成更容易阅读的格式的工具
│ │ └─ProjectCreator 生成Visual Studio的project文件的工具
│ └─vm HotSpot VM的核心代码
│ ├─adlc 平台描述文件(上面的cpu或os_cpu里的*.ad文件)的编译器
│ ├─asm 汇编器接口
│ ├─c1 client编译器(又称“C1”)
│ ├─ci 动态编译器的公共服务/从动态编译器到VM的接口
│ ├─classfile 类文件的处理(包括类加载和系统符号表等)
│ ├─code 动态生成的代码的管理
│ ├─compiler 从VM调用动态编译器的接口
│ ├─gc_implementation GC的实现
│ │ ├─concurrentMarkSweep Concurrent Mark Sweep GC的实现
│ │ ├─g1 Garbage-First GC的实现(不使用老的分代式GC框架)
│ │ ├─parallelScavenge ParallelScavenge GC的实现(server VM默认,不使用老的分代式GC框架)
│ │ ├─parNew ParNew GC的实现
│ │ └─shared GC的共通实现
│ ├─gc_interface GC的接口
│ ├─interpreter 解释器,包括“模板解释器”(官方版在用)和“C++解释器”(官方版不在用)
│ ├─libadt 一些抽象数据结构
│ ├─memory 内存管理相关(老的分代式GC框架也在这里)
│ ├─oops HotSpot VM的对象系统的实现
│ ├─opto server编译器(又称“C2”或“Opto”)
│ ├─prims HotSpot VM的对外接口,包括部分标准库的native部分和JVMTI实现
│ ├─runtime 运行时支持库(包括线程管理、编译器调度、锁、反射等)
│ ├─services 主要是用来支持JMX之类的管理功能的接口
│ ├─shark 基于LLVM的JIT编译器(官方版里没有使用)
│ └─utilities 一些基本的工具类
└─test 单元测试
好像最新的源码结构中没有src\share\tools\launcher
参考链接如下:
https://blog.csdn.net/dviewer/article/details/77972217
使用 Visual Studio 编译出的 HotSpot 是虚拟机,是作为动态链接库的形式被 java.exe
载入的。java.exe
负责解析參数,载入虚拟机链接库,它须要调用虚拟机中的函数来完毕运行 Java 程序的功能。所以,你在HotSpot的源码中找不到启动的程序的 main
函数,本来在 openjdk7 中,虚拟机是带有一个启动器的,在文件夹 openjdk/hotspot/src/share/tools/launcher/java.c
中能够找到 main 函数,可是在 openjdk8 中,这个启动器不见了,被放在 openjdk/jdk
文件夹下,而不是 openjdk/hotspot
文件夹下
1.设置VS2010 x64环境变量
运行C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64\vcvars.bat
2.修改cygwin路径
D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\hotspot\make\windows\create.bat
3.创建hotspot工程空间
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
create.bat功能说明
REM This is the interactive build setup script (as opposed to the batch
REM build execution script). It creates $HotSpotBuildSpace if necessary,
REM copies the appropriate files out of $HotSpotWorkSpace into it, and
REM builds and runs ProjectCreator in it. This has the side-effect of creating
REM the vm.vcproj file in the buildspace, which is then used in Visual C++.
在hotspot build目录下D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\hotspot\build\vs-amd64
4.解压编译好jdk/bin/jdk.diz
D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\build\windows-x86_64-normal-server-fastdebug\jdk\bin
利用vs2010打开D:\openjdk-8u40-src-b25-10_feb_2015\openjdk\hotspot\build\vs-amd64\jvm.vcproj
配置编译参数Compiler2 Fastdebug + X64
项目右击属性配置
Debugging中
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
public class Test {
public static void main(String[] args) {
System.out.println("hello world");
}
}
编译产生class文件
使用-Djava.class.path来指定class文件位置
添加断点 share\vm\runtime\thread.cpp,line 3305, create_vm
剩下就可以结合源码来学习jvm内部原理了。
参考链接:
https://www.jianshu.com/p/e85f93cc74cb
https://www.cnblogs.com/dennyzhangdd/p/6734933.html