OpenJDK系列(一):编译/调试与项目结构

OpenJDK编译

之前的基于OpenJDK8的资料由于人为因素丢失了,索性就重新来过:以OpenJDK10为例.此外,如无特殊说明,开发平台皆为MacOS.最新文章见浮游.

源码下载

在mac平台上,可以通过HomeBrew进行OpenJDK源码的下载,以OpenJDK10为例.由于OpenJDK的源码采用mercurial进行管理,因此需要安装mercurial,另外由于编译需要,我们同时安装ccache和freetype工具:

 brew install mercurial
 brew install install ccache
 brew install freetype

接下来通过以下命令正式进行下载:

 hg clone http://hg.openjdk.java.net/jdk10/jdk10 OpenJDK10
 # 进入OpenJDK10目录下执行命令
 bash ./get_source.sh
image-20180903153521528

现在我们已经将所有的源码下载到本地了,接下来我们可以进行编译来满足下好奇心,

编译

在正式编译之前需要我们先配置编译信息,该过程通过configure.sh脚本实现,其存放在OpenJDK源码的根目录.使用该脚本需要制定一些参数参数,在mac平台下,配置如下:

./configure --with-target-bits=64 --with-freetype=/usr/local/Cellar/freetype/2.9.1 --enable-ccache --with-jvm-variants=server,client --with-boot-jdk-jvmargs="-Xlint:deprecation -Xlint:unchecked" --disable-zip-debug-info --disable-warnings-as-errors --with-debug-level=slowdebug 2>&1 | tee configure_mac_x64.log

注意不要写错freetype的路径,可以通过 brew list freetype命令来查看当前freetype的安装路径.

configure中提供了大量的参数,通过命令bash ./configure --help=short,当然你也可以直接查看OpenJDK的官方说明,这里我们只是简单介绍几个:

参数 含义
--with-target-bits 设置32为/64编译
--with-freetype 指定freetype目录
--with-jvm-variants=server,client 设置要构建的JVM的变体,目前可以选择server,client,minimal,core,zero,zeroshark,custom
--with-boot-jdk-jvmargs 设置运行boot JDK所需要的JVM参数,例如--with-boot-jdk-jvmargs="-Xmx8G"
--with-debug-level 调试等级,目前可以指定为release,fastdebug,是slowdebug,optimized

编译信息配置后之后,通过以下命令进行编译即可:

 export LANG=C
 make all LOG=debug 2>&1 | tee make_mac_x64.log

期间可能会遇到一些编译问题,大多可以官网找到方法,编译的产物会被存放在build目录下:

image-20180903161446477

执行以下命令,验证下编译结果

cd OpenJDK10/build/macosx-x86_64-normal-serverANDclient-slowdebug/jdk/bin
./java -version
image-20180903161734147

OpenJDK调试

对于OpenJDK调试而言,常用的工具有gdb和lldb,在MacOS使用更多的是lldb.直接使用lldb进行调试,相对比较原始,对于比较复杂的项目还可以借助Xcode或者CLion.

Xcode调试OpenJDK

以Xcode 9为例.

工程创建

首先使用Xcode创建一个新的项目OpenSDK10,为Command Line Tool类型.

step1

点击Next继续配置其他信息.

step2

创建完成后,先删除默认生成的文件.

step3

源码导入

右键OpenJDK10,选则Add Files To "OpenJDK10",将之前用于OpenJDK10的源码根目录下的文件都添加进来.

step4
step5

现在我们来配置下项目.选择Product -> Scheme -> Edit Scheme.在左侧的Run选项中先配置info标签页中的Executable,此处指定为之前我们已经编译好的java命令,按照我们之前的编译配置,此处路径即为:

/OpenJDK10/build/macosx-x86_64-normal-serverANDclient-slowdebug/jdk/bin/java

step9

接下来继续配置Arguments标签页中的Arguments Passed On Launch.随便写的一个Hello.java文件,如下内容:

public class Hello{
    public static void main(String[] args){
          System.out.println("Hello World !");
    }
}

然后将其放在java命令所在的目录,即上述提到的/OpenJDK10/build/macosx-x86_64-normal-serverANDclient-slowdebug/jdk/bin中,在该目录下执行'./javac Hello.java'将其编译成class文件.

step8

开始调试

到现在,所有的准备工作已经做好了,可以进行调试了.在main.c的main()打几个断点后开始调试.

step10

到现在已经可以正常调试了,但继续调试可能会遇到signal SIGSEGV错误

step11

此时只需要在lldb中设置(lldb) process handle SIGSEGV --stop=false,然后继续调试即可.

step12

不出意外,最终我们会在lldb控制台看到输出结果"Hello World ! ",如下:

step12

至此关于Xcode下调试OpenJDK源码的流程已经完成.

源码目录结构

OpenJDK源码结构如下:

image-20180903162039612
目录 说明
build OpenJDK编译产物
common
corba 包含corba功能源代码
hotspot 包含Hotspot虚拟机实现源码
jaxp jaxp功能的源代码,用于处理XML,提供了
jaxws jax-ws功能的源代码,用于构建Web服务的API
jdk 包含Java工具包
langtool 语言工具的源代码如javac,javap等
nashorn JavaScript引擎实现

hotspot

jdk是我们平时开发主要关注的地方,而hotspot使我们了解虚拟机重要的目录,下面我们来了解hotspot目录,重点来看其src子目录:

image-20180903163506096
目录 说明
make 编译流程控制
src VM源码
test 单元测试代码

src目录下包含了有关VM实现的代码:

image-20180903165531524

cpu

不同平台上CPU相关的代码,

image-20180903164728943

os

不同操作系统相关代码.根据不同的系统分为不同的目录

image-20180903164636220

os_cpu

操作系统和cpu组合的相关代码.

image-20180903164806923

share

与具体平台无关的代码.该目录下又分为tools和vm目录.其中tools中提供了相关工具代码.vm是虚拟机实现的核心代码.

image-20180903165455427

tools

目录 说明
hsdis 反汇编工具
idealGraphVisualizer 中间代码可视化工具
LogCompilation 将使用-XX:LogCompiliation输出的日志格式化更容易阅读的工具

vm

目录 说明
adlc 平台描述文件的编译器
aot aot编译器实现,用于静态编译
asm 汇编器接口
c1 Client编译器,即我们常说的C1编译器
ci 动态编译器公共接口
classfile 类文件处理
code 管理动态生成的代码
compiler VM调用动态编译器的接口
gc GC的实现,包含cms,g1,parallel,serial目录(对应四种GC器实现代码)以及有关GC器的公共代码实现目录shared
interpreter 解释器的实现,模板解释器和C++解释器
jvmci JVM编译器接口
libadt 抽象数据结构
logging VM通过日志记录系统
memory 内存管理相关
metaprogramming
oops HotSpot中关于对象系统的实现
opto Server编译器,即我们常说的C2编译器
precompiled
prims VM对外接口以及jvmti(用于调试)实现
runtime 运行时支持库,比如线程管理,锁,反射等
services 支持JMX之类的管理功能的接口
shark 基于LLVM的JIT编译器
trace
utilities 一些工具类代码

推荐阅读更多精彩内容