环境信息
macOS Catalina 10.15
环境准备
JDK 8
1
2
3
4$ java -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
下载源码
下载源码有两种方式:
从 openjdk 的 mercurial 仓库下载, 本地安装 mercurial 后执行如下命令:
1
2
3$ hg clone http://hg.openjdk.java.net/jdk8/jdk8 JDK8
$ cd JDK8
$ bash ./get_source.sh打开http://jdk.java.net/, 选择版本, 在新页面的RI Source Code区域, 点击zip file连接, 下载源码压缩包, 这种方式下载下来的源码版本是固定的.
这里采用第二种方式, 并将下载下来的 zip 包解压到 openjdk8
目录
系统准备
先创建一个
envsetup.sh
, 写入以下内容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设定语言选项,必须设置
export LANG=C
Mac平台,C编译器不再是GCC,是clang
export CC=gcc
跳过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
并行编译的线程数,编译时间长,为了不影响其他工作,我选择为2
export HOTSPOT_BUILD_JOBS=2
是否跳过与先前版本的比较
export SKIP_COMPARE_IMAGES=true
是否使用预编译头文件,加快编译速度
export USE_PRECOMPILED_HEADER=true
是否使用增量编译
export INCREMENTAL_BUILD=true
编译内容
export BUILD_LANGTOOLS=true
export BUILD_JAXP=false
export BUILD_JAXWS=false
export BUILD_CORBA=false
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
加上产生调试信息时需要的 objcopy
export OBJCOPY=gobjcopy然后执行命令:
source envsetup.sh
Xcode 10 以后移除了 libstdc++ 的支持, 但 hotspot 编译时还需要依赖这个过期 5 年的库, 因此需要从 Xcode9 中拷贝出libstdc++和 c++包, 复制到响应位置. 也可以打开 这个链接, clone 到本地,参考
install.sh
将文件链接或者复制到对应位置(慎重直接执行, 请一定事先核对路径是否正确!)
configure
在 openjdk8 目录下执行以下命令
1 | $ bash ./configure \ |
错误1
1 | configure: error: GCC compiler is required. Try setting --with-tools-dir. |
编辑common/autoconf/generated-configure.sh
, 搜索 GCC compiler is required
, 在搜索结果的每一行加上#
, 注释掉, 例如:
1 | # as_fn_error $? "GCC compiler is required. Try setting --with-tools-dir." "$LINENO" 5 |
错误 2
1 | checking if we should generate debug symbols... configure: error: Unable to find objcopy, cannot enable debug-symbols |
因为没有正确执行上面的envsetup.sh
文件, 解决办法:1
$ source envsetup.sh
再次执行 configure
命令后, 输出如下成功信息1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23====================================================
A new configuration has been successfully created in
/Users/tonnyyi/workspace/sourceCode/openjdk8/build/macosx-x86_64-normal-server-slowdebug
using configure arguments '--with-target-bits=64 --with-debug-level=slowdebug --enable-debug-symbols ZIP_DEBUGINFO_FILES=0'.
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_191" Java(TM) SE Runtime Environment (build 1.8.0_191-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode) (at /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home)
* C Compiler: version (at /usr/bin/gcc)
* C++ Compiler: version (at /usr/bin/g++)
Build performance summary:
* Cores to use: 4
* Memory limit: 16384 MB
* ccache status: installed, but disabled (version older than 3.1.4)
Build performance tip: ccache gives a tremendous speedup for C++ recompilations.
You have ccache installed, but it is a version prior to 3.1.4. Try upgrading.
make
执行如下命令:1
$ make all LOG=debug 2>&1 | tee make_mac_x64.log
错误 1
1 | if (Universe::narrow_oop_base() > 0) { // Implies UseCompressedOops. |
编辑hotspot/src/share/vm/opto/lcm.cpp
文件, 作如下调整1
2// if (Universe::narrow_oop_base() > 0) { // Implies UseCompressedOops.
if (Universe::narrow_oop_base() != NULL) { // Implies UseCompressedOops.
错误 2
1 | assert(rng->Opcode() == Op_LoadRange || _igvn.type(rng)->is_int() >= 0, "must be"); |
编辑hotspot/src/share/vm/opto/loopPredicate.cpp
文件, 做如下调整1
2//assert(rng->Opcode() == Op_LoadRange || _igvn.type(rng)->is_int() >= 0, "must be");
assert(rng->Opcode() == Op_LoadRange || _igvn.type(rng)->is_int()->_lo >= 0, "must be");
错误 3
1 | if (base() > 0) { |
编辑hotspot/src/share/vm/runtime/virtualspace.cpp
, 做如下调整:1
2// if (base() > 0) {
if (base() != 0) {
错误 4
1 | #import <JavaNativeFoundation/JavaNativeFoundation.h> |
因为 Xcode 之前会安装类似 xxx-for-java-command-lines-tools 的框架包到 /System/Library/Frameworks, 而自从 macOS 10.14 开始, 这些框架包全部都被安装到了 /Library/Developer/CommandLineTools/SDKs/MacOSX10.1x.sdk, 首先执行如下命令行1
2
3
4
5$ find / -name "*JavaNativeFoundation.h*"
...
/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Frameworks/JavaNativeFoundation.framework/Versions/A/Headers/JavaNativeFoundation.h
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Frameworks/JavaNativeFoundation.framework/Versions/A/Headers/JavaNativeFoundation.h
...
得到了真正的JavaVM.framework
是被安装到了/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk
目录下
编辑hotspot/make/bsd/makefiles/saproc.make
文件, 作如下调整, 加上路径前缀/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk
1
2# SALIBS = -g -framework Foundation -F/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation
SALIBS = -g -framework Foundation -F/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/JavaVM.framework/Frameworks -framework JavaNativeFoundation -framework Security -framework CoreFoundation
1 | # -I/System/Library/Frameworks/JavaVM.framework/Headers |
错误 5
1 | #import <CoreGraphics/CGBase.h> |
这个问题和上面一样, 需要编辑两个文件
jdk/make/lib/PlatformLibraries.gmk
jdk/make/lib/Awt2dLibraries.gmk
将包含 ApplicationServices.framework
的路径前替换成/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/CoreGraphics.framework
将包含 JavaVM.framwork
的路径替换成/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/JavaVM.framework/Frameworks
错误 6
1 | Undefined symbols for architecture x86_64: |
编辑jdk/src/macosx/native/sun/osxapp/ThreadUtilities.m
, 作如下调整1
2// inline void attachCurrentThread(void** env) {
static inline void attachCurrentThread(void** env) {
编译完成
1 | ## Finished docs (build time 00:01:39) |
测试验证
执行如下命令1
$ build/macosx-x86_64-normal-server-slowdebug/jdk/bin/java -version
错误 1
1 | # |
编辑hotspot/src/share/vm/runtime/perfMemory.cpp
的perfMemory_exit()
函数, 作如下调整:1
2
3
4
5if (!StatSampler::is_active())
PerfDataManager::destroy();
if (!StatSampler::is_active())
// PerfDataManager::destroy();
然后再次重新编译1
$ make all LOG=debug 2>&1 | tee make_mac_x64.log
但是这样处理后,使用jstat监控JVM时可能会导致 内存泄露
再次验证1
2
3
4$ build/macosx-x86_64-normal-server-slowdebug/jdk/bin/java -version
openjdk version "1.8.0-internal-debug"
OpenJDK Runtime Environment (build 1.8.0-internal-debug-tonnyyi_2019_11_11_14_52-b00)
OpenJDK 64-Bit Server VM (build 25.40-b25-debug, mixed mode)
参考资料
https://www.jianshu.com/p/ee7e9176632c
https://imkiva.com/2018/02/24/building-openjdk8-on-macos/
https://juejin.im/post/5a6d7d106fb9a01ca47abd8b
http://menzhongxin.com/2017/04/27/MAC%E4%B8%8B%E7%BC%96%E8%AF%91openJDK/
https://iyichen.xyz/2019/10/mac-compile-openjdk/