Mac上编译OpenJDK9源码

为什么编译可调式的OpenJdk源码

学习一段时间JAVA之后,关于Java方面的知识总还能找到解决办法,但是一旦涉及到虚拟机,有的时候就茫然无头绪,不知道如何去解决,此时就需要一个可调试的虚拟机代码。同时想要更好的了解虚拟机原理,自己编译一个可debug的JVM则必不可少,本文就是介绍在mac上自己编译一个JVM。

为什么要用mac去编译?

因为jvm源码比较复杂,有一系列的运行环境依赖,所以在mac上更容易去获取这些依赖。

前人蹚过的坑

不要编译JDK 8: 因为编译JDK 8需要Xcode 4现在Xcode版本已远高于4了(这个坑是前人蹚出来的,当然我不信邪,然后自己蹚了一遍,然后发现确实是个坑)

尽量不要使用Mercurial来下Open JDK的源码,而用浏览器直接下载打包好的源码: 因为你要用Mercurial下载了Open JDK的顶层工程后,还需要执行其中的get_source.sh来下载其子工程的源码,这个过程漫长而且失败率高(关键还没有执行百分比提示,干等),用浏览器自己下载所有子工程的压缩包要快很多,而且成功率100%(我自己蹚出来的,前人的几篇文章中全告诉我用Mercurial,结果坑了)

编译JDK 9u而不是JDK 9因为我当时编译9的时候出了一堆error,所以我想带个u的是不是会好些,当然这个有很大程度是我臆测的,我后期就都拿9u搞了,没试9,如果各位有兴趣可以自己蹚蹚这个

configure的时候一定要带上–disable-warnings-as-errors这个参数,否则编译过程中的warning也会中断编译的进程,实际上这些warning并不影响编译后的目标JDK的运行

环境描述

官方安装环境,强烈建议尽量贴近官方提供的环境,否则可能编译失败
https://wiki.openjdk.java.net/display/Build/Supported+Build+Platforms

系统:MacOS High Sierra 10.13.6
Boot JDK:1.8.0_221
Freetype:2.10
XCode CommandLineTools

源码位置

openjdk是托管在 Mercurial hg(类似于git的代码管理软件) 上的,因此打开openjdk官网,找到Source Code的Mercurial Bundles即可,具体位置:http://hg.openjdk.java.net/jdk9

开始前准备

下载完源码后,开始编译之前,请仔细阅读README,文档在下载的源码中 common/doc/building.html

环境准备

1.Boot JDK安装

编译jdk需要预先安装版本至少为N-1的JDK,这个jdk官方成为Boot JDK,比如安装openjdk9,则需要安装的jdk版本至少为jdk8。因为jdk源码里面有不少工具是java编写的,所以需要jdk进行编译。

2.ToolChain:

Command Line Tools 就是一个小型独立包,为mac终端用户提供了许多常用的工具,实用程序和编译器。包括svn,git,make,GCC,clang,perl,size,strip,strings,libtool,cpp,what以及其他很多能够在Linux默认安装中找到的有用的命令。
因为jdk底层用cpp编写的,所以需要安装cpp的环境,推荐安装!

# 按照xcode command line tools
$ xcode-select --install

# 实际按照目录:/Library/Developer/CommandLineTools/,可用命令都在目录下的 usr/bin 中

各个系统需要的toolchain不一样,官方说明如下:

Linux:gcc,
macOS:Apple Xcode (using clang)
Solaris:Oracle Solaris Studio
AIX:IBM XL C/C++
Windows:Microsoft Visual Studio

3.安装brew:

mac(或linux)上常用的软件下载安装工具,类似Linux的apt-get,如果没有安装,点这里参考官网

4.安装Mercurial hg:

hg是openjdk提供的仓库管理工具,类似git

5.安装ccache:

ccache:compiler cache,就是把已编译内容进行缓存,不用每次都需要对openjdk进行。支持gcc、Clang和其他相似编译器

6.安装freetype:

openjdk依赖于freetype

# 安装brew
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
# 安装hg
$ brew install mercurial
# 安装ccache
$ brew install ccache
# 安装freetype
$ brew install freetype

具体编译流程

$ hg clone http://hg.openjdk.java.net/jdk9/jdk9 jdk9 # 1.下载初始包
$ cd jdk9 # 进入目录
$ bash get_source.sh   # 2.下载全部源代码【如果慢的话,挂代理,或者多试几次】
$ bash configure       # 3.configure 以默认参数配置编译环境,若编译报错,需要添加 `--disable-warnings-as-errors`
$ make images          # 4.编译 OpenJDK

接下来按照流程进行尝试

1.下载初始包和全部源代码

如果运行 bash get_source.sh 时出现类似以下错误,是网络问题造成,多运行几次 bash get_source.sh,直到不出现错误为止。
若不想使用 hg clone 加 get_source.sh 下载全部源代码,可以从 OpenJDK 的 github 镜像(非官方)下载:

$ git clone -b jdk9/jdk9 https://github.com/dmlloyd/openjdk.git

2.配置编译环境

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

注意:需要按照你本机按照的freetype目录和版本进行指定参数
编译参数简介:

--with-target-bits:设置32位/64位编译
--with-freetype:设置freetype路径
--enable-ccache:设置启用ccache
--with-jvm-variants=client,server:为了保证兼容性,编译时JVM的Client和Server都会被编译
--with-boot-jdk-jvmargs:提供运行Bootstrap JDK所需要的JVM参数
--disable-zip-debug-info:禁用zip调试信息
--disable-warnings-as-errors:禁用将警告当做错误,避免因为警告而中断编译
--with-debug-level:设置调试等级
2>&1 | tee configure_mac_x64.log:将错误信息重定向至标准输出,并输出到configure_mac_x64.log

关于debug调试等级

# Set the debug level
# release: no debug information, all optimizations, no asserts.
# optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'.
# fastdebug: debug information (-g), all optimizations, all asserts
# slowdebug: debug information (-g), no optimizations, all asserts

fastdebug可以而且将比release运行得慢,因为它在运行过程中会断言很多东西。启用断言是用户在怀疑jvm错误时寻求fastdebug构建的原因:在发布构建中神秘失败的内容,通常在fastdebug中有意义地断言。另外,fastdebug允许更好的调试,因为它通常带有调试符号,并且它可以访问在发布版本中不可设置的“开发”jvm标志

执行configure如果一切正常,则会输出:

A new configuration has been successfully created in
/Users/yanghao/openjdk/jdk9-download/jdk9/build/macosx-x86_64-normal-serverANDclient-slowdebug
using configure arguments '--with-target-bits=64 --with-freetype=/usr/local/Cellar/freetype/2.10.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'.

Configuration summary:
* Debug level:    slowdebug
* HS debug level: debug
* JDK variant:    normal
* JVM variants:   server client
* OpenJDK target: OS: macosx, CPU architecture: x86, address length: 64
* Version string: 9-internal+0-adhoc.yanghao.jdk9 (9-internal)

Tools summary:
* Boot JDK:       java version "1.8.0_221" Java(TM) SE Runtime Environment (build 1.8.0_221-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)  (at /Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home)
* Toolchain:      clang (clang/LLVM)
* C Compiler:     Version 10.0.0 (at /usr/bin/clang)
* C++ Compiler:   Version 10.0.0 (at /usr/bin/clang++)

Build performance summary:
* Cores to use:   4
* Memory limit:   8192 MB
* ccache status:  Active (3.7.9)

NOTE: You have requested to build more than one version of the JVM, which
will result in longer build times.

The following warnings were produced. Repeated here for convenience:
WARNING: Option --enable-zip-debug-info is deprecated and will be ignored.
WARNING: Please use --with-native-debug-symbols=zipped .

同时会产生 build目录,下面有个macosx-x86_64-normal-serverANDclient-slowdebug 目录,后期编译的文件都存放在这里面。如果想要更换configure参数,执行以下命令进行清理configure参数:

$ make clean
$ make dist-clean

4.开始正式编译openjdk

关于编译错误

正式编译的时候,可能会复现几个编译错误,我完美复现了以下3个编译错误:https://iyichen.xyz/2019/10/mac-compile-openjdk/,请看【编译错误】

官方也有bug列表和解决方案:https://bugs.openjdk.java.net/browse/JDK-8187787。这是因为 XCode 带的 g++ 编译器版本在某些方面与 Hotspot 开发用的 c++ 编译器不兼容,导致有些代码用 XCode 的 g++ 编译会报错,官方使用的版本如下:

At the time of writing, OpenJDK has been successfully compiled on macOS versions up to 10.12.5 (Sierra), using XCode 8.3.2 and –disable-warnings-as-errors

按照说明修改源码,一切编译正常,所有的编译内容都存放在build/macosx-x86_64-normal-serverANDclient-slowdebug目录下。

编译成功

成功后测试下JDK版本

$ ./build/macosx-x86_64-normal-serverANDclient-slowdebug/jdk/bin/java -version
openjdk version "9-internal"
OpenJDK Runtime Environment (slowdebug build 9-internal+0-adhoc.yanghao.jdk9)
OpenJDK 64-Bit Server VM (slowdebug build 9-internal+0-adhoc.yanghao.jdk9, mixed mode)

阅读和调试hospot源码

我们使用 slowdebug 编译了 jdk 源代码,build 目录下会生成 java.dSYM、javac.dSYM、libjava.dylib.dSYM、libjvm.dylib.dSYM 等调试信息文件。有这些调试信息文件,就可以直接使用 gdb 或者 lldb 调试 HotSpot 了。

lldb java
(lldb) b main
Breakpoint 1: 19 locations.
(lldb) run
Process 6276 launched: '/Users/yulewei/jdk9/build/macosx-x86_64-normal-server-slowdebug/jdk/bin/java' (x86_64)
Process 6276 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100001813 java`main(argc=1, argv=0x00007fff5fbfef98) at main.c:98
   95  	{
   96  	    int margc;
   97  	    char** margv;
-> 98  	    const jboolean const_javaw = JNI_FALSE;
   99  	#endif /* JAVAW */
   100
   101 	    JLI_InitArgProcessing(!HAS_JAVA_ARGS, const_disable_argfile);
Target 0: (java) stopped.
(lldb) source info
Lines found in module `java
[0x0000000100001813-0x0000000100001817): /Users/yulewei/CODING/jdk9/jdk/src/java.base/share/native/launcher/main.c:98:20

使用CLion

之前Clion只支持 CMake,从2018.2版本开始对Makefile项目提供支持,具体支不支持还需要研究。这里未进行尝试

观云

本博客所有文章均为独立创作。 原创不易,转载请注明来源并保留原文链接,转载自观云 | yeas.fun

You may also like...

发表评论

电子邮件地址不会被公开。 必填项已用*标注