为什么编译JDK

如果想深入学习JDK内部的实现机制,最便捷的路径是自己手动编译一套JDK,通过阅读和跟踪debug JDK源码去深入了解Java技术体系的原理,结合各类书籍、文章和博客,对比理解,更容易让你了解JDK是怎么运作的,底层都做了什么。

环境准备

  • Mac OS X Catalina 10.15.1

安装依赖软件

1
$ xcode-select install
1
$ brew install mercurial

和UI界面有关, build需要引入。

  • JDK 8
1
2
3
4
$ java -version
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)
  • freetype

FreeType是一个用C语言实现的一个字体光栅化库。它可以用来将字符栅格化并映射成位图以及提供其他字体相关业务的支持。

1
$ brew install freetype
  • gcc
1
2
brew search gcc
brew install gcc@4.9
  • llvm
1
brew install llvm

添加软连接

为了防止openJDK找不不到库,所以需要加个软链链接到他们历史上曾经存在位置。

1
2
3
4
5
6
7
// llvm 
$ sudo ln -s /usr/bin/llvm-gcc /Applications/Xcode.app/Contents/Developer/usr/bin/llvm-gcc
$ sudo ln -s /usr/bin/llvm-g++ /Applications/Xcode.app/Contents/Developer/usr/bin/llvm-g++

// XQuartz
$ sudo ln -s /usr/X11/include/X11 /usr/include/X11
$ sudo ln -s /usr/X11/include/freetype2/freetype/ /usr/X11/include/freetype

新版本Mac OS X Catalina中,升级Xcode 11,其SDK中已经安装有clang以及clang++的依赖,llvm 则无需再次安装,在/usr/bin/目录我们可以通过命令查看到:

1
2
3
4
$ ll /usr/bin/llvm-g++
lrwxr-xr-x 1 root wheel 7B Nov 12 22:02 /usr/bin/llvm-g++ -> clang++
$ ll /usr/bin/llvm-gcc
lrwxr-xr-x 1 root wheel 5B Nov 12 22:02 /usr/bin/llvm-gcc -> clang

我们再查看clang和clang++的版本信息发现这两个编译工具均来源于Xcode的toolchains:

1
2
3
4
5
6
7
8
9
10
11
$ clang++ -v
Apple clang version 11.0.0 (clang-1100.0.33.12)
Target: x86_64-apple-darwin19.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

$ clang -v
Apple clang version 11.0.0 (clang-1100.0.33.12)
Target: x86_64-apple-darwin19.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

再来说说XQuartz,XQuartz下载完是一个dmg镜像包,点击安装直到完成,在安装过程中,自动会把/opt/X11软连接到/usr/include/X11,XQuartz是安装到/var/select/X11/目录下的,如果你发现没有/usr/include/X11,则需要添加软链接:ln -s /opt/X11 /usr/include/X11

下载 OpenJDK

OpenJDK 是用Mercurial做版本控制的。如果您不熟悉 Mercurial,请参阅《Mercurial入门指南》。

Mac 环境需要安装类似 Git 或 SVN 的版本控制工具 Mercurial,打开官网https://www.mercurial-scm.org/,在官网右侧有Download按钮,下面能看到Mac OS X(你可以点击当前链接进入)。我们看到mercurial有两种安装方式:第一种下载 DMG 文件安装,第二种通过命令安装,上面安装依赖中已经给出。

在 OpenJDK 官网的首页可以看到Hack on the JDK itself字样,里面就有克隆仓库(clone a Mercurial repository)的链接,点击该链接进去就会看到相关clone的命令, hg tclone http://hg.openjdk.java.net/jdk9/dev 9dev。我们需要编译JDK8,所以命令需要改动一下,OpenJDK的 mercurial 地址为:http://hg.openjdk.java.net/,根据自身情况选择适合自己的JDK版本,如图1,左侧是选择 JDK 大版本,右侧是选择 JDK 具体的版本,我们选择jdk8u60

克隆代码:

1
2
3
hg tclone http://hg.openjdk.java.net/jdk8u/jdk8u60 jdk8u
cd jdk8u
bash ./get_source.sh # 克隆完成后,使用脚本获取最新的源代码,根据网络环境的不同,这一步花费的时间不同,一般花费时间较长

拉取完成的 jdk 源码存储目录如下:

Repository Contains 备注
. (root) 通用配置和生成makefile编译文件的逻辑 主要是configure、MakeFile
hotspot 用于构建 OpenJDK 虚拟机的源代码和make文件 JVM源码
langtools OpenJDK javac 和 语言工具源码 jdk中提供的开发工具,比如javac,javap,jvisual以及一些国际化实现
jdk JDK源码和用于构建 OpenJDK 运行时库和杂项的make文件 jdk源码,编译后生成的则是Java运行时库和一些杂项库lib
jaxp OpenJDK JAXP功能的源代码
jaxws OpenJDK JAX-WS功能的源代码
corba OpenJDK Corba功能的源代码
nashorn OpenJDK JavaScript 引擎实现的源代码 Java调用JavaScript时需要的一个引擎

环境变量设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 设定语言选项,必须设置
export LANG=C
# Mac平台,C编译器不再是GCC,而是clang
export CC=clang
export CXX=clang++
export CXXFLAGS=-stdlib=libc++
# 是否使用clang,如果使用的是GCC编译,该选项应该设置为false
export USE_CLANG=true
# 跳过clang的一些严格的语法检查,不然会将N多的警告作为Error
export COMPILER_WARNINGS_FATAL=false
# 链接时使用的参数
export LFLAGS='-Xlinker -lstdc++'
# 使用64位数据模型
export LP64=1
# 告诉编译平台是64位,不然会按照32位来编译
export ARCH_DATA_MODEL=64
# 允许自动下载依赖
export ALLOW_DOWNLOADS=true
# 并行编译的线程数,编译时长,为了不影响其他工作,可以选择2
export HOTSPOT_BUILD_JOBS=2
export PARALLEL_COMPILE_JOBS=2 #ALT_PARALLEL_COMPILE_JOBS=2
# 是否跳过与先前版本的比较
export SKIP_COMPARE_IMAGES=true
# 是否使用预编译头文件,加快编译速度
export USE_PRECOMPILED_HEADER=true
# 是否使用增量编译
export INCREMENTAL_BUILD=true
# 编译内容
export BUILD_LANGTOOL=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_BULID=false
export DEBUG_NAME=debug
# 避开javaws和浏览器Java插件之类部分的build
export BUILD_DEPLOY=false
export BUILD_INSTALL=false

# 最后需要干掉这两个环境变量(如果你配置过),不然会发生诡异的事件
unset JAVA_HOME
unset CLASSPATH

将上面的环境变量设置 bash 窗口执行(只在当前 bash 窗口生效)或者将其保存在当前用于目录的 ~/.bahs_profile中(全局生效,bash 窗口需要重新打开)或者保存在单独的一个脚本envsetup.sh中均可。

1
open ~/.bash_profile # source envsetup.sh

复制粘贴之后,保存~/.bahs_profile,然后 source 应用使其生效:source ~/.bash_profile

编译OpenJdk

需要注意是,编译 jdk 需要预先安装一个JDK,可以是不同的版本,用于启动,通过参数--with-boot-jdk=${YOUR_JDK_HOME}来指定。

configure

1
bash ./configure --with-debug-level=slowdebug --with-freetype-include=/usr/local/include/freetype2 --with-freetype-lib=/usr/local/lib --with-boot-jdk=/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home --with-native-debug-symbols=internal
  • –with-debug-level 设置编译级别,在这里我们要编译为能够debug的版本,因此设为slowdebug。
  • –with-native-debug-symbols 生成调试需要debug符号信息,并将这些信息写入到编译生成的二进制文件中,该参数一定要指定,否则用gdb调试的时候会提示找不到符号信息,无法设置断点。

如果配置成功,configure 执行结束时则在控制台最后输出如下信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
====================================================
A new configuration has been successfully created in
/Users/joyven/Documents/workspace/jdk8u/build/macosx-x86_64-normal-server-slowdebug
using configure arguments '--with-debug-level=slowdebug --with-freetype-include=/usr/local/include/freetype2 --with-freetype-lib=/usr/local/lib --with-boot-jdk=/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home --with-native-debug-symbols=internal'.

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.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: gcc (GNU Compiler Collection)
* C Compiler: Version Apple clang version 11.0.0 (clang-1100.0.33.12) Target: x86_64-apple-darwin19.0.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin (at /usr/bin/clang)
* C++ Compiler: Version Apple clang version 11.0.0 (clang-1100.0.33.12) Target: x86_64-apple-darwin19.0.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin (at /usr/bin/clang++)

Build performance summary:
* Cores to use: 2
* Memory limit: 16384 MB

WARNING: You have old-style ALT_ environment variables set.
These are not respected, and will be ignored. It is recommended
that you clean your environment. The following variables are set:
ALT_PARALLEL_COMPILE_JOBS=2

WARNING: The result of this configuration has overridden an older
configuration. You *should* run 'make clean' to make sure you get a
proper build. Failure to do so might result in strange build problems.

make all

1
make all

make如果不出错,则会在10分钟左右输出下面信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
----- Build times -------
Start 2019-11-19 10:30:24
End 2019-11-19 10:51:10
00:00:34 corba
00:01:25 demos
00:03:02 docs
00:04:18 hotspot
00:02:39 images
00:00:36 jaxp
00:00:54 jaxws
00:06:05 jdk
00:00:58 langtools
00:00:15 nashorn
00:20:46 TOTAL
-------------------------
Finished building OpenJDK for target 'all'

测试一下是否编译OK:

1
build/macosx-x86_64-normal-server-slowdebug/jdk/bin/java -version

输出如下说明编译成功:

1
2
3
openjdk version "1.8.0-internal-debug"
OpenJDK Runtime Environment (build 1.8.0-internal-debug-joyven_2019_11_19_11_50-b00)
OpenJDK 64-Bit Server VM (build 25.71-b00-debug, mixed mode)

configure阶段遇到的错误

问题1:Cannot locate autoconf, unable to correct situation

错误信息

1
2
3
4
5
Configure source code has been updated, checking time stamps
Warning: The configure source files is newer than the generated files.
Cannot locate autoconf, unable to correct situation.
Please install autoconf and run 'bash autogen.sh' to update the generated files.
Error: Cannot continue

解决方法

1
brew install autoconf

问题2:Xcode 4 is required to build JDK 8, the version found was 11.1

错误信息

1
2
3
checking for xcodebuild... /usr/bin/xcodebuild
configure: error: Xcode 4 is required to build JDK 8, the version found was 11.1. Use --with-xcode-path to specify the location of Xcode 4 or make Xcode 4 active by using xcode-select.
configure exiting with result code 1

解决方法

找到 configure 文件并打开common/autoconf/generated-configure.sh,找到判断版本的地方,将这一段全部注释掉。

1
2
3
4
5
6
# 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

问题3:A gcc compiler is required. Try setting --with-tools-dir

错误信息

1
2
3
4
5
6
7
8
9
checking for xcodebuild... /usr/bin/xcodebuild
checking Determining Xcode SDK path... /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk
configure: Will use user supplied compiler CC=clang
checking for clang... /usr/bin/clang
checking resolved symbolic links for CC... no symlink
configure: The C compiler (located as /usr/bin/clang) does not seem to be the required gcc compiler.
configure: The result from running with --version was: ""
configure: error: A gcc compiler is required. Try setting --with-tools-dir.
configure exiting with result code 1

解决方法

还是找到刚刚的文件common/autoconf/generated-configure.sh,有五处校验的地方(从27881行开始),找到并且注释掉校验的逻辑。

1
2
3
4
5
6
7
8
9
10
11
if test $? -ne 0; then
ALT_VERSION_OUTPUT=`$COMPILER --version 2>&1`
{ $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 with -V was: \"$COMPILER_VERSION_OUTPUT\"" >&5
$as_echo "$as_me: The result from running with -V was: \"$COMPILER_VERSION_OUTPUT\"" >&6;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&5
$as_echo "$as_me: The result from running with --version was: \"$ALT_VERSION_OUTPUT\"" >&6;}
as_fn_error $? "A $TOOLCHAIN_TYPE compiler is required. Try setting --with-tools-dir." "$LINENO" 5
fi

问题4:fatal error: ‘iostream’ file not found

错误信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Compiling /Users/joyven/Documents/workspace/jdk8u/hotspot/src/share/vm/adlc/adlparse.cpp
warning: include path for stdlibc++ headers not found; pass '-stdlib=libc++' on the command line to use the libc++ standard library instead [-Wstdlibcxx-not-found]
Compiling /Users/joyven/Documents/workspace/jdk8u/hotspot/src/share/vm/adlc/archDesc.cpp
In file included from /Users/joyven/Documents/workspace/jdk8u/hotspot/src/share/vm/adlc/adlparse.cpp:27:
/Users/joyven/Documents/workspace/jdk8u/hotspot/src/share/vm/adlc/adlc.hpp:35:10: fatal error: 'iostream' file not found
#include <iostream>
^~~~~~~~~~
warning: include path for stdlibc++ headers not found; pass '-stdlib=libc++' on the command line to use the libc++ standard library instead [-Wstdlibcxx-not-found]
In file included from /Users/joyven/Documents/workspace/jdk8u/hotspot/src/share/vm/adlc/archDesc.cpp:27:
/Users/joyven/Documents/workspace/jdk8u/hotspot/src/share/vm/adlc/adlc.hpp:35:10: fatal error: 'iostream' file not found
#include <iostream>
^~~~~~~~~~
1 warning and 1 error generated.
1 warning and 1 error generated.
make[6]: *** [../generated/adfiles/adlparse.o] Error 1
make[6]: *** Waiting for unfinished jobs....
make[6]: *** [../generated/adfiles/archDesc.o] Error 1
make[5]: *** [ad_stuff] Error 2
make[4]: *** [debug] Error 2
make[3]: *** [generic_build2] Error 2
make[2]: *** [debug] Error 2
make[1]: *** [/Users/joyven/Documents/workspace/jdk8u/build/macosx-x86_64-normal-server-slowdebug/hotspot/_hotspot.timestamp] Error 2
make: *** [hotspot-only] Error 2

解决方法

更新最新的Xcode11,并且安装xcode命令行工具:

1
2
# export LDFLAGS='-Xlinker -stdlib=libc++'
xcode-select --install

问题5:clang: error: linker command failed with exit code 1 (use -v to see invocation)

错误信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
## Starting hotspot
make[2]: warning: -jN forced in submake: disabling jobserver mode.
Warning: The jvmg target has been replaced with debug
Warning: Please update your usage
INFO: ENABLE_FULL_DEBUG_SYMBOLS=1
INFO: ENABLE_FULL_DEBUG_SYMBOLS=1
Making adlc
clang: warning: libstdc++ is deprecated; move to libc++ with a minimum deployment target of OS X 10.9 [-Wdeprecated]
ld: library not found for -lstdc++
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[6]: *** [../generated/adfiles/adlc] Error 1
make[5]: *** [ad_stuff] Error 2
make[4]: *** [debug] Error 2
make[3]: *** [generic_build2] Error 2
make[2]: *** [debug] Error 2
make[1]: *** [/Users/joyven/Documents/workspace/jdk8u/build/macosx-x86_64-normal-server-slowdebug/hotspot/_hotspot.timestamp] Error 2
make: *** [hotspot-only] Error 2

解决方法

原因:这个原因是Xcode升级到10以后就没有包含lstdc++库了。而 hotspot 居然还一直用着这个,于是编译器找不到 libstdc++ 的头文件就罢工了
解决办法:
打开 这个链接, clone 到本地,参考 install.sh 将文件链接或者复制到对应位置(慎重直接执行,请一定事先核对路径是否正确)!

1
2
3
sudo mkdir Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++
sudo cp -R ../ios/xcode-missing-libstdc-/include/c++/* /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++
sudo cp ../ios/xcode-missing-libstdc-/lib/* /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/

或者,将/usr/lib中的库文件拷贝到Xcode相应的文件夹中,并设置相关的软连接:

1
2
3
4
sudo cp /usr/lib/libstdc++.6.0.9.dylib /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/
cd /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/
sudo ln -s libstdc++.6.0.9.dylib libstdc++.6.dylib
sudo ln -s libstdc++.6.dylib libstdc++.dylib

问题6:configure: error: C compiler cannot create executables

See `config.log’ for more details

1
2
3
4
5
6
7
8
9
10
11
12
13
configure: Using default toolchain gcc (GNU Compiler Collection)
checking Determining if we need to set DEVELOPER_DIR... no
checking for xcodebuild... /usr/bin/xcodebuild
checking Determining Xcode SDK path... /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk
configure: Will use user supplied compiler CC=clang
checking for clang... /usr/bin/clang
checking resolved symbolic links for CC... no symlink
configure: Using gcc C compiler version Apple clang version 11.0.0 (clang-1100.0.33.8) Target: x86_64-apple-darwin19.0.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin [Apple clang version 11.0.0 (clang-1100.0.33.8) Target: x86_64-apple-darwin19.0.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin]
checking whether the C compiler works... no
configure: error: in `/Users/joyven/Documents/workspace/jdk8u':
configure: error: C compiler cannot create executables
See `config.log' for more details
configure exiting with result code 77

查看config.log,发现如下错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Apple clang version 11.0.0 (clang-1100.0.33.8)
Target: x86_64-apple-darwin19.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
configure:28126: $? = 0
configure:28115: /usr/bin/clang -V >&5
clang: error: unsupported option '-V -Wno-framework-include-private-from-public'
clang: error: no input files
configure:28126: $? = 1
configure:28115: /usr/bin/clang -qversion >&5
clang: error: unknown argument '-qversion', did you mean '--version'?
clang: error: no input files
configure:28126: $? = 1
configure:28146: checking whether the C compiler works
configure:28168: /usr/bin/clang -Xlinker -stdlib=libc++ conftest.c >&5
ld: unknown option: -stdlib=libc++
clang: error: linker command failed with exit code 1 (use -v to see invocation)
configure:28172: $? = 1
configure:28210: result: no
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME "OpenJDK"
| #define PACKAGE_TARNAME "openjdk"
| #define PACKAGE_VERSION "jdk8"
| #define PACKAGE_STRING "OpenJDK jdk8"
| #define PACKAGE_BUGREPORT "build-dev@openjdk.java.net"
| #define PACKAGE_URL "http://openjdk.java.net"
| /* end confdefs.h. */
|
| int
| main ()
| {
|
| ;
| return 0;
| }
configure:28215: error: in `/Users/joyven/Documents/workspace/jdk8u':
configure:28217: error: C compiler cannot create executables
See `config.log' for more details

解决方法

安装最新版本的Xcode11,同时xcode-select需要重新安装:

1
xcode-select install

然后,

1
sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/* /usr/local/include/
1
2
3
export CC=clang
export CXX=clang++
export CXXFLAGS=-stdlib=libc++

问题7:Undefined symbols for architecture x86_64

错误信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
## Starting hotspot
make[2]: warning: -jN forced in submake: disabling jobserver mode.
Warning: The jvmg target has been replaced with debug
Warning: Please update your usage
INFO: ENABLE_FULL_DEBUG_SYMBOLS=1
INFO: ENABLE_FULL_DEBUG_SYMBOLS=1
Making adlc
clang: warning: libstdc++ is deprecated; move to libc++ with a minimum deployment target of OS X 10.9 [-Wdeprecated]
Undefined symbols for architecture x86_64:
"std::__1::locale::use_facet(std::__1::locale::id&) const", referenced from:
std::__1::num_put<char, std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > > const& std::__1::use_facet<std::__1::num_put<char, std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > > >(std::__1::locale const&) in filebuff.o
std::__1::ctype<char> const& std::__1::use_facet<std::__1::ctype<char> >(std::__1::locale const&) in filebuff.o
"std::__1::ios_base::getloc() const", referenced from:
std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(int) in filebuff.o
std::__1::basic_ios<char, std::__1::char_traits<char> >::widen(char) const in filebuff.o
"std::__1::ctype<char>::id", referenced from:
std::__1::ctype<char> const& std::__1::use_facet<std::__1::ctype<char> >(std::__1::locale const&) in filebuff.o
"std::__1::locale::~locale()", referenced from:
std::__1::basic_ostream<char, std::__1::char_traits<char> >::operator<<(int) in filebuff.o
std::__1::basic_ios<char, std::__1::char_traits<char> >::widen(char) const in filebuff.o
"std::__1::num_put<char, std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > >::id", referenced from:
std::__1::num_put<char, std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > > const& std::__1::use_facet<std::__1::num_put<char, std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > > >(std::__1::locale const&) in filebuff.o
"std::__1::ios_base::clear(unsigned int)", referenced from:
std::__1::ios_base::setstate(unsigned int) in filebuff.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[6]: *** [../generated/adfiles/adlc] Error 1
make[5]: *** [ad_stuff] Error 2
make[4]: *** [debug] Error 2
make[3]: *** [generic_build2] Error 2
make[2]: *** [debug] Error 2
make[1]: *** [/Users/joyven/Documents/workspace/jdk8u/build/macosx-x86_64-normal-server-slowdebug/hotspot/_hotspot.timestamp] Error 2
make: *** [hotspot-only] Error 2

解决方法

先设置环境变量,重新configure:

1
2
3
export CC=clang
export CXX=clang++ # 或者 export CXX=g++
export CXXFLAGS=-stdlib=libc++

make阶段遇到的问题

问题1:invalid argument ‘-std=gnu++98’ not allowed with ‘C’

错误信息

1
2
3
4
5
6
7
8
9
10
Making signal interposition lib...
error: invalid argument '-std=gnu++98' not allowed with 'C'
make[6]: *** [libjsig.dylib] Error 1
make[6]: *** Waiting for unfinished jobs....
make[5]: *** [the_vm] Error 2
make[4]: *** [debug] Error 2
make[3]: *** [generic_build2] Error 2
make[2]: *** [debug] Error 2
make[1]: *** [/Users/joyven/Documents/workspace/jdk8u/build/macosx-x86_64-normal-server-slowdebug/hotspot/_hotspot.timestamp] Error 2
make: *** [hotspot-only] Error 2

解决方法

${Your_JDK_DIR}/common/autoconf/generated-configure.sh文件中找到参数“-std=gnu++98”,将代码注释如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
if test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then
CFLAGS_JDKLIB_EXTRA="${CFLAGS_JDKLIB_EXTRA} -xregs=no%appl"
CXXFLAGS_JDKLIB_EXTRA="${CXXFLAGS_JDKLIB_EXTRA} -xregs=no%appl"
fi
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
LDFLAGS_JDK="${LDFLAGS_JDK} -q64 -brtl -bnolibpath -liconv -bexpall"
CFLAGS_JDK="${CFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt"
CXXFLAGS_JDK="${CXXFLAGS_JDK} -qchars=signed -q64 -qfullpath -qsaveopt"
elif test "x$TOOLCHAIN_TYPE" = xgcc; then
LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS -fstack-protector"
LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS -fstack-protector"
if test "x$OPENJDK_TARGET_OS" != xmacosx; then
LDFLAGS_JDK="$LDFLAGS_JDK -Wl,-z,relro"
LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS -Wl,-z,relro"
fi
# CXXSTD_CXXFLAG="-std=gnu++98" # 注释掉这行

之后重新运行configure,再执行make all。

问题2:A fatal error has been detected by the Java Runtime Environment

错误信息

执行命令:

1
build/macosx-x86_64-normal-server-slowdebug/jdk/bin/java -version

报错信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
openjdk version "1.8.0-internal-debug"
OpenJDK Runtime Environment (build 1.8.0-internal-debug-joyven_2019_11_19_10_28-b00)
OpenJDK 64-Bit Server VM (build 25.71-b00-debug, mixed mode)
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGILL (0x4) at pc=0x0000000110c3ae38, pid=84856, tid=0x0000000000002803
#
# JRE version: OpenJDK Runtime Environment (8.0) (build 1.8.0-internal-debug-joyven_2019_11_19_10_28-b00)
# Java VM: OpenJDK 64-Bit Server VM (25.71-b00-debug mixed mode bsd-amd64 compressed oops)
# Problematic frame:
# V [libjvm.dylib+0xa3ae38] PerfData::~PerfData()+0x8
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /Users/joyven/Documents/workspace/jdk8u/hs_err_pid84856.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#

[error occurred during error reporting , id 0x4]

[2] 84856 abort build/macosx-x86_64-normal-server-slowdebug/jdk/bin/java -version

解决方法

根据这个错误提示,我们可以知道错误发生在动态链接库 libjvm.dylib中,根据提示,错误代码是在PerfData::~PerfData()函数中。因此我们需要对这个函数进行修改,即文件 hotspot/src/share/vm/runtime/perfData.cpp,函数内容如下:

1
2
3
4
5
6
7
8
PerfData::~PerfData() {
if (_name != NULL) {
FREE_C_HEAP_ARRAY(char, _name, mtInternal);
}
if (is_on_c_heap()) {
FREE_C_HEAP_ARRAY(PerfDataEntry, _pdep, mtInternal);
}
}

发现并有其他东西,可以完全注释掉整个函数体内容,但在在这两篇博客编译openjdk遇到的问题MacOS Mojave(10.14)编译openjdk9 中找到的发现他们的解决思路是找到PerfDataManager::destroy()函数,将代码"delete p"注释掉,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void PerfDataManager::destroy() {

if (_all == NULL)
// destroy already called, or initialization never happened
return;

for (int index = 0; index < _all->length(); index++) {
PerfData* p = _all->at(index);
// delete p;
}

delete(_all);
delete(_sampled);
delete(_constants);

_all = NULL;
_sampled = NULL;
_constants = NULL;
}