以前看JVM代码都是用VSCode或者Sublime直接翻看源代码,虽然方便但是却不是很直观,不如编译下OpenJDK使用工具进行Debug .Here we go.

环境与准备工作

OpenJDK8有专门的构建描述文档(当然这个文档在你download下来的文件夹中也有),编译之前一定要仔细阅读文档(虽然坑也挺多 ).

  • OS : macOS High Sierra 10.13.6
  • GNU make : 3.8.1(文档要求>=3.8.1,可使用make -version来查看版本)
  • OpenJDK(编译) : jdk8u
  • BootstrapJDK(引导JDK,用来构建被编译JDK的Java部分) : 1.7.0_80(文档要求JDK7,Mac下切换JDK可以参考)
  • freetype : 2.10.1(一个字体引擎,文档要求>=2.3)
    安装freetype

    可以使用brew进行安装$ brew install freetype

  • Mercurial : 5.2_1(无版本要求,OpenJDK8使用的版本控制系统,拉取代码用)
    安装Mercurial

    可以使用brew进行安装$ brew install mercurial

首先,我们已经安装了Mercurial,让我们来clone代码

hg clone http://hg.openjdk.java.net/jdk8u/jdk8u/ MyOpenJDK

我们可以打开http://hg.openjdk.java.net/来查看OpenJDK版本(8u里面同样有跟多版本dev、8u、8u20等等).
clone成功后我们还要执行命令来获取完整的repositories,执行(执行不了请给权限)

cd MyOpenJDK 
bash ./get_source.sh

有时候网络不太好,可能下载不下来。可多尝试几次或者下载

网盘资源
.
完整的文件目录

total 648
-rw-r--r--   1 macos  staff   1.5K Jun 25 02:42 ASSEMBLY_EXCEPTION
-rw-r--r--   1 macos  staff    19K Jun 25 02:42 LICENSE
-rw-r--r--   1 macos  staff   6.2K Jun 25 02:42 Makefile
-rw-r--r--   1 macos  staff   1.5K Jun 25 02:42 README
-rw-r--r--   1 macos  staff   126K Jun 25 02:42 README-builds.html
-rw-r--r--   1 macos  staff   149K Jun 25 02:42 THIRD_PARTY_README
drwxr-xr-x   6 macos  staff   204B Jun 25 02:42 common
-rw-r--r--   1 macos  staff   1.6K Jun 25 02:42 configure
drwxr-xr-x  12 macos  staff   408B Jun 25 02:44 corba
-rwxrwxrwx   1 macos  staff   3.0K Jun 25 02:42 get_source.sh
drwxr-xr-x  14 macos  staff   476B Jun 25 02:48 hotspot
drwxr-xr-x  16 macos  staff   544B Jun 25 02:45 jaxp
drwxr-xr-x  16 macos  staff   544B Jun 25 02:45 jaxws
drwxr-xr-x  13 macos  staff   442B Jun 25 02:55 jdk
drwxr-xr-x  13 macos  staff   442B Jun 25 02:45 langtools
drwxr-xr-x  12 macos  staff   408B Jun 25 02:42 make
drwxr-xr-x  20 macos  staff   680B Jun 25 02:48 nashorn
drwxr-xr-x   4 macos  staff   136B Jun 25 02:42 test

继续阅读文档,发现其他系统都有一大堆要求,而对于macOS只有短短几个要求:
Install XCode 4.5.2 and also install the "Command line tools" found under the preferences pane "Downloads".
Make sure you get the right XCode version.
那么问题就来了,现在高版本的Mac哪还有XCode4.X的啊大哥,去官网工具看了下XCode 4.5.2 requires OS X Mountain Lion or OS X Lion.高版本的macOS根本不支持XCode的4.5.2版本,而且我也不想装新版的XCode(太鸡儿大了).

其实从XCode4.2开始,macOS默认的编译器就从GCC变成了Clang.我们虽然可以用GCC命令,但是其实已经被替换成Clang(我们之前安装所用的brew在安装的时候会自动为我们安装CommandLineTools这个命令行工具,我们在安装后输入gcc -v会发现控制台出现的其实是clang).

我翻阅了部分资料,发现大家一般有两种解决方式:

1. 继续使用OpenJDK默认的GCC编译器进行编译

GCC安装

brew install gcc@4.94.9是目前brew安装所允许的最低的版本了,超过5会因为默认启用c++14导致编译中断


此时我们要把被替换的GCC与G++命令替换成我们新安装的

#备份之前的
sudo mkdir /usr/bin/backup && sudo mv /usr/bin/gcc /usr/bin/g++ /usr/bin/backup
#创建新的链接
sudo ln -s /usr/local/Cellar/gcc@4.9/4.9.4_2/bin/gcc-4.9 /usr/bin/gcc
sudo ln -s /usr/local/Cellar/gcc@4.9/4.9.4_2/bin/g++-4.9 /usr/bin/g++
    

但是不同的OpenJDK8编译脚本加载的可能不一样,为了保险起见,我们还要修改CommandLineTools的

#备份之前的
sudo mkdir /Library/Developer/CommandLineTools/usr/bin/backup && sudo mv /Library/Developer/CommandLineTools/usr/bin/gcc
/Library/Developer/CommandLineTools/usr/bin/g++
/Library/Developer/CommandLineTools/usr/bin/backup
#创建新的链接
sudo ln -s /usr/local/Cellar/gcc@4.9/4.9.4_2/bin/gcc-4.9 /Library/Developer/CommandLineTools/usr/bin/gcc
sudo ln -s /usr/local/Cellar/gcc@4.9/4.9.4_2/bin/g++-4.9 /Library/Developer/CommandLineTools/usr/bin/g++

我并没有采取这种方式,可以参考这篇博客《Building OpenJDK 8 on Mac OS X Mavericks》

2. 使用Clang进行编译

因为我之前已经安装了CommandLineTools,输入命令GCC -v发现

Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 10.0.0 (clang-1000.10.44.4)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

此时我的clang版本为:Apple LLVM version 10.0.0 (clang-1000.10.44.4),所以不用再去装贼大的新版XCode。
我们首先要修改环境变量(如果你使用bash就修改~/.bash_profile,如果你是zsh就修改~/.zshrc),此处变量设置参考R大的回答:Mac OS X 10.9.2 build JDK8有谁build成功过么

# 设定语言选项,必须设置
export LANG=C
# Mac平台,C编译器不再是GCC,是clang
export CC=clang
# 跳过clang的一些严格的语法检查,不然会将N多的警告作为Error
export COMPILER_WARNINGS_FATAL=false
# 链接时使用的参数
export LFLAGS='-Xlinker -lstdc++'
# 是否使用clang
export USE_CLANG=true
# 使用64位数据模型
export LP64=1
# 告诉编译平台是64位,不然会按32位来编译
export ARCH_DATA_MODEL=64
# 允许自动下载依赖
export ALLOW_DOWNLOADS=true
# 并行编译的线程数
export HOTSPOT_BUILD_JOBS=4
# 是否跳过与先前版本的比较
export SKIP_COMPARE_IMAGES=true
# 是否使用预编译头文件,加快编译速度
export USE_PRECOMPILED_HEADER=true
# 是否使用增量编译
export INCREMENTAL_BUILD=true
# 编译内容
export BUILD_LANGTOOLS=true
export BUILD_JAXP=true
export BUILD_JAXWS=true
export BUILD_CORBA=true
export BUILD_HOTSPOT=true
export BUILD_JDK=true
# 编译版本
export SKIP_DEBUG_BUILD=true
export SKIP_FASTDEBUG_BUILD=false
export DEBUG_NAME=debug
# 避开javaws和浏览器Java插件之类的部分的build
export BUILD_DEPLOY=false
export BUILD_INSTALL=false
unset JAVA_HOME

修改完记得source ~/.zshrc哦.

配置

下面我们可以来进行configure了,文档里面有对众多参数的说明,让我们选几个重要的使用

  • --with-freetype-include=/usr/local/include/freetype2
  • --with-freetype-lib=/usr/local/lib/ 这两条是为了防止找不到freetype报错
  • --with-debug-level=slowdebug 启用slowdebug级别调试
  • --with-boot-jdk=/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home 设定Bootstrap JDK
  • --with-target-bits=64 指定JVM为64位
  • --with-num-cores=8 编译使用CPU核心数
  • --with-memory-size=8000 编译使用内存
  • --with-jvm-variants=server 编译server类型JVM

开始啦

bash ./configure  --with-freetype-include=/usr/local/include/freetype2 --with-freetype-lib=/usr/local/lib/ --with-debug-level=slowdebug --with-boot-jdk=/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home --with-target-bits=64 --with-num-cores=8 --with-memory-size=8000 --with-jvm-variants=server   

不出意外,果然报错啦

xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance
configure: error: Xcode 4 is required to build JDK 8, the version found was . Use --with-xcode-path to specify the location of Xcode 4 or make Xcode 4 active by using xcode-select.

第一个错误我们可以不用去管它,因为我们没下XCode,所以没法使用xcodebuild的构建工具,但是xcodebuild只是方便你使用XCode,我们完全可以使用CLion来日后进行Debug而不是XCode.而第二个错误,我们打开目录下的configure文件,发现执行的是

bash -c ". $this_script_dir/common/autoconf/configure" $this_script_dir/configure CHECKME $this_script_dir "$@"

OK,继续进入到common、autoconf目录下查看configure,发现最后执行的是generated-configure.sh这个shell文件.打开generated-configure.sh,根据刚才的报错信息找到

# Fail-fast: verify we're building on Xcode 4, we cannot build with Xcode 5 or later
    XCODE_VERSION=`$XCODEBUILD -version | grep '^Xcode ' | sed 's/Xcode //'`
    XC_VERSION_PARTS=( ${XCODE_VERSION//./ } )
    if test ! "${XC_VERSION_PARTS[0]}" = "4"; then
      as_fn_error $? "Xcode 4 is required to build JDK 8, the version found was $XCODE_VERSION. Use --with-xcode-path to specify the location of Xcode 4 or make Xcode 4 active by using xcode-select." "$LINENO" 5
    fi

可见即使我们按照信息所说的设置--with-xcode-path也是会报错的,简单粗暴一点,这段代码直接注释掉好了

go on,go on!继续执行配置命令,发现出现了新的错误

configure: error: A gcc compiler is required. Try setting --with-tools-dir.

继续去generated-configure.sh中寻找,找到多处

if test $? -ne 0; then
      { $as_echo "$as_me:${as_lineno-$LINENO}: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&5
$as_echo "$as_me: The $COMPILER_NAME compiler (located as $COMPILER) does not seem to be the required $TOOLCHAIN_TYPE compiler." >&6;}
      { $as_echo "$as_me:${as_lineno-$LINENO}: The result from running it was: \"$COMPILER_VERSION_OUTPUT\"" >&5
$as_echo "$as_me: The result from running it was: \"$COMPILER_VERSION_OUTPUT\"" >&6;}
      as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5
    fi

继续注释大法,走你

====================================================
A new configuration has been successfully created in
/Users/macos/server/MyOpenJDK8/build/macosx-x86_64-normal-server-slowdebug
using configure arguments '--with-freetype-include=/usr/local/include/freetype2 --with-freetype-lib=/usr/local/lib/ --with-debug-level=slowdebug --with-boot-jdk=/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home --with-target-bits=64 --with-num-cores=8 --with-memory-size=8000 --with-jvm-variants=server'.

Configuration summary:
* Debug level:    slowdebug
* JDK variant:    normal
* JVM variants:   server
* OpenJDK target: OS: macosx, CPU architecture: x86, address length: 64

Tools summary:
* Boot JDK:       java version "1.7.0_80" Java(TM) SE Runtime Environment (build 1.7.0_80-b15) Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)  (at /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home)
* Toolchain:      gcc (GNU Compiler Collection)
* C Compiler:     Version 10.0.0 (at /usr/bin/clang)
* C++ Compiler:   Version 10.0.0 (at /usr/bin/g++)

Build performance summary:
* Cores to use:   7
* Memory limit:   8000 MB

NND,成功了 至于核心数为啥是7,估计是取值取到我的CPU核心数只有8给我留了一个干其他工作吧,还真是人性化呢.....

构建

make all

又报错了

error: invalid argument '-std=gnu++98' not allowed with 'C'

generated-configure.sh中使用注释大法

CXXSTD_CXXFLAG="-std=gnu++98"

make clean清理一下后,删除MyOpenJDK/build下之前configure出来的文件夹,继续执行之前configure的命令,再次make all.还是TNND报错

Undefined symbols for architecture x86_64:
  "_attachCurrentThread", referenced from:
      +[ThreadUtilities getJNIEnv] in ThreadUtilities.o
      +[ThreadUtilities getJNIEnvUncached] in ThreadUtilities.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

此处参考了文章,打开MyOpenJDK/jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m, 将inline void attachCurrentThread(void** env) { 修成成static inline void attachCurrentThread(void** env) {
继续make clean、删除MyOpenJDK/build下之前configure出来的文件夹、configure、make all的步骤

----- Build times -------
Start 2020-06-25 05:37:01
End   2020-06-25 05:45:12
00:00:23 corba
00:00:20 demos
00:01:51 docs
00:01:20 hotspot
00:00:42 images
00:00:15 jaxp
00:00:21 jaxws
00:02:17 jdk
00:00:29 langtools
00:00:13 nashorn
00:08:11 TOTAL
-------------------------
Finished building OpenJDK for target 'all'

乌拉!成功啦!进入MyOpenJDK/build/xxxxx(名称可能不同)/jdk/bin下java -version

java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)

Nice!当然有可能在java -version后出现

java version "1.8.0_151"
    Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
    Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
#
# A fatal error has been detected by the Java Runtime Environment:
#

当然我这次是没出现这个错误,但是之前有一个8的版本出现了问题,可以参考文章《编译openjdk遇到的问题》,将hotspot/src/share/vm/runtime/perfData.cpp文件中的PerDataManager::destroy()函数中的代码"delete p"注释掉。

美滋滋,编译完成 ,接下来可以通过IDE工具愉快的Debug啦!

Last modification:June 25th, 2020 at 07:13 am
大家一起分享知识,分享快乐