深入理解Java虚拟机(2)之一-macOS下编译openjdk10


==因为电脑系统版本和软件版本都比较高,在编译jdk7和jdk8的时候出现各种各样的问题,编译jdk10一次就ok了。==

编译openjdk10

编译环境

  • 系统环境 :macOS Mojave 10.14.3
  • 编译器 :clang
  • openJdk :openjdk10
  • boostrap JDK :oracle jdk1.8.0_202
  • xcode version :9.4.1(xcode 10libc++替换了stdlibc++)
  • ant version :1.10.5
  • freetype 2.10.0
  • ccache 3.7.1

获取源码

Mercurial代码管理工具从仓库下载

brew install mercurial
hg clone http://hg.openjdk.java.net/jdk10/jdk10/ jdk10
cd jdk10
chmod 755 get_source.sh
./get_source.sh

配置环境变量env.sh

# 设定语言选项,必须设置
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
# 并行编译的线程数
export HOTSPOT_BUILD_JOBS=4
# 已过时
# export ALT_PARALLEL_COMPILE_JOBS=4
# 是否跳过与先前版本的比较
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 env.sh

# configure
bash ./configure \
    --with-target-bits=64 \
    --with-debug-level=slowdebug \
    --disable-warnings-as-errors \
    --with-freetype=/usr/local/Cellar/freetype/2.10.0/ \
    --enable-ccache

完成后出现以下内容:

====================================================
The existing configuration has been successfully updated in
/Users/qliang/Documents/code/openjdk/jdk10/build/macosx-x86_64-normal-server-slowdebug
using configure arguments '--with-target-bits=64 --with-debug-level=slowdebug --disable-warnings-as-errors --with-freetype=/usr/local/Cellar/freetype/2.10.0/ --enable-ccache'.

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

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

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

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 clean
make all

成功出现以下信息:

Finished building target 'default (exploded-image)' in configuration 'macosx-x86_64-normal-server-slowdebug'

验证

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

出现:

openjdk version "10-internal"
OpenJDK Runtime Environment (slowdebug build 10-internal+0-adhoc.qliang.jdk10)
OpenJDK 64-Bit Server VM (slowdebug build 10-internal+0-adhoc.qliang.jdk10, mixed mode)

编译openjdk8

编译环境

  • 系统环境 :macOS Mojave 10.14.3
  • 编译器 :clang
  • openJdk :openjdk8
  • boostrap JDK :oracle jdk1.8.0_202
  • xcode version :10.1 (10B61)
  • ant version :1.10.5
  • XQuartz 2.7.11

获取源码

Mercurial代码管理工具从仓库下载

brew install mercurial
hg clone http://hg.openjdk.java.net/jdk8u/jdk8u-dev/ JDK8u
cd JDK8
chmod 755 get_source.sh
./get_source.sh

配置环境变量env.sh

# 设定语言选项,必须设置
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
# 并行编译的线程数
export HOTSPOT_BUILD_JOBS=4
export ALT_PARALLEL_COMPILE_JOBS=4
# 是否跳过与先前版本的比较
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 env.sh

# configure
bash ./configure \
    --with-target-bits=64 \
    --with-debug-level=slowdebug \
    --disable-warnings-as-errors \
    --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_202" Java(TM) SE Runtime Environment (build 1.8.0_202-b08) Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)  (at /Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home)
* C Compiler:      version  (at /usr/bin/gcc)
* C++ Compiler:    version  (at /usr/bin/g++)

Build performance summary:
* Cores to use:   2
* Memory limit:   16384 MB
* ccache status:  not installed (consider installing)

执行make


遇到的问题

  1. configure: error: GCC compiler is required. Try setting --with-tools-dir.

解决方案

修改 common/autoconf/generated-configure.sh

搜索 GCC compiler is required

对应内容注释掉。

  1. error: Xcode 4 is required to build JDK 8

解决方案

修改 common/autoconf/generated-configure.sh

搜索 error: Xcode 4 is required to build JDK 8,注释对应5行

两行内容注释掉。

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

解决方案

修改 common/autoconf/generated-configure.sh

搜索 -std=gnu++98,注释

两行内容注释掉

2.

/Users/qliang/Documents/code/JDK8/hotspot/src/share/vm/code/relocInfo.hpp:367:27: error: friend declaration specifying a default argument must be a definition
  inline friend relocInfo prefix_relocInfo(int datalen = 0);
                          ^
/Users/qliang/Documents/code/JDK8/hotspot/src/share/vm/code/relocInfo.hpp:462:18: error: friend declaration specifying a default argument must be the only declaration
inline relocInfo prefix_relocInfo(int datalen) {
                 ^
/Users/qliang/Documents/code/JDK8/hotspot/src/share/vm/code/relocInfo.hpp:367:27: note: previous declaration is here
  inline friend relocInfo prefix_relocInfo(int datalen = 0);
                          ^
/Users/qliang/Documents/code/JDK8/hotspot/src/share/vm/code/relocInfo.hpp:463:21: error: 'fits_into_immediate' is a protected member of 'relocInfo'
  assert(relocInfo::fits_into_immediate(datalen), "datalen in limits");
                    ^
/Users/qliang/Documents/code/JDK8/hotspot/src/share/vm/code/relocInfo.hpp:375:15: note: declared protected here
  static bool fits_into_immediate(int data0) {
              ^
/Users/qliang/Documents/code/JDK8/hotspot/src/share/vm/code/relocInfo.hpp:464:59: error: 'RAW_BITS' is a protected member of 'relocInfo'
  return relocInfo(relocInfo::data_prefix_tag, relocInfo::RAW_BITS, relocInfo::datalen_tag | datalen);
                                                          ^
/Users/qliang/Documents/code/JDK8/hotspot/src/share/vm/code/relocInfo.hpp:272:23: note: declared protected here
  enum RawBitsToken { RAW_BITS };
                      ^
/Users/qliang/Documents/code/JDK8/hotspot/src/share/vm/code/relocInfo.hpp:464:10: error: calling a protected constructor of class 'relocInfo'
  return relocInfo(relocInfo::data_prefix_tag, relocInfo::RAW_BITS, relocInfo::datalen_tag | datalen);
         ^
/Users/qliang/Documents/code/JDK8/hotspot/src/share/vm/code/relocInfo.hpp:273:3: note: declared protected here
  relocInfo(relocType type, RawBitsToken ignore, int bits)
  ^

解决方案

修改 hotspot/src/share/vm/code/relocInfo.hpp

367行 int datalen = 0 改为 int datalen

462行 int datalen 改为 int datalen = 0

  1. /Users/qliang/Documents/code/JDK8/hotspot/src/share/vm/opto/loopPredicate.cpp:775:73: error: ordered comparison between pointer and zero ('const TypeInt *' and 'int')
       assert(rng->Opcode() == Op_LoadRange || _igvn.type(rng)->is_int() >= 0, "must be");
                                               ~~~~~~~~~~~~~~~~~~~~~~~~~ ^  ~

解决方案

_igvn.type(rng)->is_int() >= 0 改为 _igvn.type(rng)->is_int()->_lo >= 0

  1. /Users/qliang/Documents/code/JDK8/hotspot/src/share/vm/runtime/virtualspace.cpp:331:14: error: ordered comparison between pointer and zero ('char *' and 'int')
    if (base() > 0) {
       ~~~~~~ ^ ~

解决方案

base() > 0 改为 base() != 0

  • 一定要出现编码错误再修改文件,不然会报错误
/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home//bin/javac  -J-XX:ThreadStackSize=1536 -J-XX:-PrintVMOptions -J-XX:+UnlockDiagnosticVMOptions -J-XX:-LogVMOutput -J-Xmx512m -J-Xms512m -J-XX:PermSize=32m -J-XX:MaxPermSize=160m -encoding -source 6 -target 6 -d /Users/qliang/Documents/code/jvm/openjdk_7u/corba/btclasses \
        -sourcepath ../../tools/src ../../tools/src/build/tools/stripproperties/StripProperties.java
javac: 无效的标记: 6
用法: javac <options> <source files>
-help 用于列出可能的选项
make[4]: *** [/Users/qliang/Documents/code/jvm/openjdk_7u/corba/btjars/stripproperties.jar] Error 2
make[3]: *** [build] Error 1
make[2]: *** [build] Error 1
make[1]: *** [corba-build] Error 2
make: *** [build_product_image] Error 2
hotspot/src/share/vm/adlc/archDesc.cpp:335:35: error: '&&' within '||'
      [-Werror,-Wlogical-op-parentheses]
export COMPILER_WARNINGS_FATAL=false

5.

clang: error: unknown argument: '-fpch-deps'

解决方案

修改 hotspot/make/bsd/makefiles/gcc.make

# 注释217-219行
# Flags for generating make dependency flags.
# ifneq ("${CC_VER_MAJOR}", "2")
# DEPFLAGS = -fpch-deps -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
# endif

6.高版本的gcc不再支持编译选项stabs

487 warnings and 4 errors generated.
make[8]: *** [precompiled.hpp.gch] Error 1
make[7]: *** [the_vm] Error 2
make[6]: *** [product] Error 2
make[5]: *** [generic_build2] Error 2
make[4]: *** [product] Error 2
make[3]: *** [all_product_universal] Error 2
make[2]: *** [universal_product] Error 2
make[1]: *** [hotspot-build] Error 2
make: *** [build_product_image] Error 2

完成

## Finished jdk (build time 00:03:28)

----- Build times -------
Start 2019-03-18 20:53:08
End   2019-03-18 21:00:51
00:00:23 corba
00:02:48 hotspot
00:00:13 jaxp
00:00:20 jaxws
00:03:28 jdk
00:00:31 langtools
00:07:43 TOTAL
-------------------------
Finished building OpenJDK for target 'default'

==以下为编译openjdk7出现的各种问题,最终没有编译成功。==

编译openjdk7

编译环境

  • 系统环境 :macOS Mojave 10.14.3
  • 编译器 :clang
  • openJdk :jdk7u-dev
  • boostrap JDK :oracle jdk1.7.0_80
  • xcode version :10.1 (10B61)
  • ant version :1.9.13

获取源码

Mercurial代码管理工具从仓库下载

brew install mercurial
hg clone http://hg.openjdk.java.net/jdk7u/jdk7u-dev
cd jdk7u-dev
chmod 755 get_source.sh
./get_source.sh

直接下载官方打包的源代码


配置环境变量env.sh

#语言选项,这个必须设置,否则编译好后会出现一个HashTable的NPE错
export LANG=C

#Bootstrap JDK的安装路径。必须设置。 
export ALT_BOOTDIR=/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/

#允许自动下载依赖
export ALLOW_DOWNLOADS=true

#并行编译的线程数,设置为和CPU内核数量一致即可
export HOTSPOT_BUILD_JOBS=6
export ALT_PARALLEL_COMPILE_JOBS=6

#比较本次build出来的映像与先前版本的差异。这个对我们来说没有意义,必须设置为false,否则sanity检查会报缺少先前版本JDK的映像。如果有设置dev或者DEV_ONLY=true的话这个不显式设置也行。 
export SKIP_COMPARE_IMAGES=true

#使用预编译头文件,不加这个编译会更慢一些
export USE_PRECOMPILED_HEADER=true

export COMPILER_WARNINGS_FATAL=false

#要编译的内容
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=false
#export SKIP_FASTDEBUG_BUILD=true
#export DEBUG_NAME=debug

#把它设置为false可以避开javaws和浏览器Java插件之类的部分的build。 
BUILD_DEPLOY=false

#把它设置为false就不会build出安装包。因为安装包里有些奇怪的依赖,但即便不build出它也已经能得到完整的JDK映像,所以还是别build它好了。
BUILD_INSTALL=false

#编译结果所存放的路径
export ALT_OUTPUTDIR=/Users/qliang/Documents/code/jvm/openjdk_7u

#这两个环境变量必须去掉,不然会有很诡异的事情发生(我没有具体查过这些“”诡异的事情”,Makefile脚本检查到有这2个变量就会提示警告“)
unset JAVA_HOME
unset CLASSPATH

export ALT_FREETYPE_HEADERS_PATH=/usr/local/include/freetype2
export ALT_FREETYPE_LIB_PATH=/usr/local/Cellar/freetype/2.9.1/lib

# export JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8

# make 2>&1 | tee $ALT_OUTPUTDIR/build.log
source env.sh

# 检查
make sanity 

Sanity check passed.
即可进行编译

遇到的问题

  1. llvm-gcc找不到
    /bin/sh: /Library/Developer/CommandLineTools/usr/bin/llvm-gcc: No such file or directory

解决方案

cd /Library/Developer/CommandLineTools/usr/bin/
# 软连接
sudo ln -s gcc llvm-gcc

2.FreeType版本过低

ERROR: FreeType version  2.3.0  or higher is required.

解决方案:环境变量添加如下

export ALT_FREETYPE_HEADERS_PATH=/usr/local/include/freetype2
export ALT_FREETYPE_LIB_PATH=/usr/local/Cellar/freetype/2.9.1/lib
  1. 主版本 52 比 51 新, 此编译器支持最新的主版本。

解决方案

boostrap JDK版本太高,降低版本
  1. 编码问题
/Users/qliang/Documents/code/jvm/openjdk_7u/corba/gensrc/com/sun/corba/se/spi/activation/Locator.java:6: 错误: 编码ascii的不可映射字符
* ���IDL-to-Java ��������� (���������), ������ "3.2"������

解决方案

借鉴于 https://0x9e370001.iteye.com/blog/1729802 修改文件的方法

文件: /corba/make/common/shared/Defs-java.gmk

133行
JAVACFLAGS += -encoding ascii
改为
#JAVACFLAGS += -encoding ascii

194行
BOOT_JAVACFLAGS  += -encoding ascii -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION)
改为

BOOT_JAVACFLAGS  += -encoding -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION)
  • 一定要出现编码错误再修改文件,不然会报错误
/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home//bin/javac  -J-XX:ThreadStackSize=1536 -J-XX:-PrintVMOptions -J-XX:+UnlockDiagnosticVMOptions -J-XX:-LogVMOutput -J-Xmx512m -J-Xms512m -J-XX:PermSize=32m -J-XX:MaxPermSize=160m -encoding -source 6 -target 6 -d /Users/qliang/Documents/code/jvm/openjdk_7u/corba/btclasses \
        -sourcepath ../../tools/src ../../tools/src/build/tools/stripproperties/StripProperties.java
javac: 无效的标记: 6
用法: javac <options> <source files>
-help 用于列出可能的选项
make[4]: *** [/Users/qliang/Documents/code/jvm/openjdk_7u/corba/btjars/stripproperties.jar] Error 2
make[3]: *** [build] Error 1
make[2]: *** [build] Error 1
make[1]: *** [corba-build] Error 2
make: *** [build_product_image] Error 2
hotspot/src/share/vm/adlc/archDesc.cpp:335:35: error: '&&' within '||'
      [-Werror,-Wlogical-op-parentheses]
export COMPILER_WARNINGS_FATAL=false

5.

clang: error: unknown argument: '-fpch-deps'

解决方案

修改 hotspot/make/bsd/makefiles/gcc.make

# 注释217-219行
# Flags for generating make dependency flags.
# ifneq ("${CC_VER_MAJOR}", "2")
# DEPFLAGS = -fpch-deps -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
# endif

6.高版本的gcc不再支持编译选项stabs

487 warnings and 4 errors generated.
make[8]: *** [precompiled.hpp.gch] Error 1
make[7]: *** [the_vm] Error 2
make[6]: *** [product] Error 2
make[5]: *** [generic_build2] Error 2
make[4]: *** [product] Error 2
make[3]: *** [all_product_universal] Error 2
make[2]: *** [universal_product] Error 2
make[1]: *** [hotspot-build] Error 2
make: *** [build_product_image] Error 2

该文章来源《深入理解Java虚拟机》读后实践

以上


文章作者: Qliang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Qliang !
评论
 上一篇
深入理解Java虚拟机(2)之二-运行时数据区域 深入理解Java虚拟机(2)之二-运行时数据区域
运行时数据区域 程序计数器(Program Counter Register): 线程私有,一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的方法实现
2019-06-12
下一篇 
SpringMVC SpringMVC
一、跟踪Spring MVC请求 请求的第一站是Spring的DispatcherServlet,DispatcherServlet查询一个或多个处理器映射(Handler Mappering),处理映射器会根据请求携带的URL信息来决策
2019-03-26
  目录