LearnJava
  • Summary
    • Introduction
    • MyResume
  • 开发
    • 小程序
      • 小程序开发问题总结
      • 小程序bug
    • 环境搭建
      • Linux搭建git服务器
      • Linux切换JDK版本
      • Mac搭建http服务器
      • Ubuntu搭建C++开发环境
      • ProtoBuffer安装
      • Ubuntu开启Telnet
      • Linux搭建邮件服务器
    • 遇到的问题
      • Mac下eclipse问题
      • Mac下Github问题
      • Markdown解决方案实例
      • Spring问题
  • 编程语言
    • C++
      • C&C++框架汇总
      • C++Primer课后习题记录
      • C++疑问
      • C++与java的异同
      • C++内存模型
      • C++知识点
      • Make和Cmake
    • GO
      • Go语言简介
      • Go语言知识点
    • XML
      • XML知识点
  • 技术学习
    • JavaIO
      • AIO通信
      • IO和NIO
      • 阻塞式IO通信
      • 非阻塞式IO通信
    • 计算机网络
      • CDN
      • HTTPS协议入门
      • HTTP_POST请求的数据格式
      • HTTP错误码和出现场景
      • HTTP协议入门
      • TCP/IP协议入门
      • Wireshark抓包
      • 域名解析过程
    • 计算机原理
      • 整型计算
      • GPU
      • Swap内存
    • 架构学习
      • 分布式锁
      • 分布式系统的CAP理论
      • IaaS,PaaS,SaaS的区别
      • Web框架
      • 康威定律
      • 秒杀系统设计
      • 数据异构
      • 微服务架构入门
      • 协程
      • MQ推拉模式对比
      • UML图
      • 缓存穿透击穿和雪崩
    • 前端学习
      • 安装使用VUE
      • 搭建VUE项目
    • 大数据
      • Hadoop之HBASE
      • Hadoop之HDFS
      • Hadoop之MapReduce
      • Hadoop简介
    • 数据结构
      • 二叉树
      • 图
      • 跳表
      • Bitmap
    • 算法
      • 排序算法
        • 插入排序
        • 归并排序
        • 计数排序
        • 快速排序
        • 冒泡排序
        • 选择排序
      • Hash算法
      • MD5介绍
      • 一致性Hash算法
      • 数字全排列
      • MD5介绍
      • 储水量
      • 最大子序列
    • Java多线程
      • AQS原理
      • AtomicInteger原理
      • Condition
      • Fork/Join框架
      • happens-before
      • Java锁优化
      • Java线程池
      • Java中的阻塞队列
      • Java实现线程的三种方式
      • Lock
      • Lock的种类
      • ThreadLocal
      • 线程状态及其转换
    • Java设计模式
      • Builder模式
      • 代理模式
      • 工厂和抽象工厂模式
      • 观察者模式
      • 设计模式概述
      • 职责链模式
      • 装饰者模式
      • Java实现单例的5种方式
    • Java学习
      • Java拓展学习
        • JavaSPI
      • Java序列化
      • Java异常
      • Java注解
      • 学习UML图
      • Java的Lambda表达式
      • Java集合之ArrayList
      • Java集合之HashMap
      • Java集合之LinkedList
      • List⤅&Set的操作和遍历
      • JavaP反编译命令
      • Servlet学习
    • JVM学习
      • 分层编译
      • Java进程内存占用
      • JVM参数
      • JVM常用工具
      • JVM的内存模型
      • 垃圾回收机制
      • 看懂gc日志
      • 类加载机制和双亲委派模型
      • 类的反射
      • 自己动手编译OPENJDK
      • ASM字节码增强技术
      • CodeCache
      • GC耗时案例
      • JVM性能调优
    • Linux学习
      • gdb调试定位
      • Linux常用命令
      • Linux工具
      • Linux进程通信的方式
      • Linux文件系统结构
      • Linux系统知识点
      • Linux小技巧
      • Shell学习
      • Vim常用命令
    • Java设计模式
      • 设计模式概述
      • 代理模式
      • 装饰者模式
    • Mysql
      • InnoDB介绍
      • Mac_mysql问题
      • mysql之group_concat函数
      • mysql事务
      • Mysql优化
      • Mysql实用命令
      • mysql慢查询
      • mysql文件
      • mysql视图
      • mysql锁
      • mysql索引
      • mysql约束
      • 存储过程和触发器
      • mysql常用语法
    • Spring
      • SpringCloud
        • 搭建Jenkins自动部署
        • SpringCloud介绍
        • SpringCloudBus
        • SpringCloudConfig
        • SpringCloudEureka
        • SpringCloudFeign
        • SpringCloudHystrix
        • SpringCloudRibbon
        • SpringCloudSleuth
        • SpringCloudStream
        • SpringCloudZuul
      • FactoryBean理解
      • MyBatis入门介绍
      • rose框架学习
      • SpringMVC的启动流程
      • SpringBean的生命周期
      • SpringBoot入门
      • Spring入门AOP和IOC
      • SpringMVC入门笔记
      • SpringMVC集成Log4j2
      • web.xml详解
    • web中间件学习
      • Redis
        • Redis入门
        • Redis持久化
        • Redis的数据类型
        • Redis特性
      • Gremlin入门
      • Elasticsearch安装使用
      • HugeGraph入门
      • jetty介绍
      • Kafka介绍使用
      • Maven安装配置
      • Netty介绍使用
      • Netty的编解码
      • Maven的pom介绍
      • Nginx介绍
      • Nginx配置详解
      • ProtocolBuffers学习笔记
      • Resin学习
      • RESTful入门
      • RocketMQ入门
      • RPC入门
      • Thrift介绍
      • Tomcat常用配置
      • Tomcat学习
      • Tomcat实现
      • zookeeper入门
      • Zookerper选举原理
  • 文档读后感
    • 除了写代码你还会干什么
  • 效率提升
    • Java诊断工具Arthas
    • Mac下安装多版本java
    • Mac下显示git分支
    • Mac中Clion快捷键
    • Mac中Eclipse快捷键
    • MacShell常用快捷键
    • PlantUML入门
    • Windows与Linux服务器传文件
    • Sublime技巧
    • 搜索引擎检索技巧
  • 总结
    • 2017工作总结
Powered by GitBook
On this page
  • 自己编译JDK(macOS)
  • 1. 获取JDK源码
  • 2. 构建编译环境
  • 3. 进行编译
  • 4. 可能遇到的错误以及解决办法

Was this helpful?

  1. 技术学习
  2. JVM学习

自己动手编译OPENJDK

Previous类的反射NextASM字节码增强技术

Last updated 4 years ago

Was this helpful?

自己编译JDK(macOS)

1. 获取JDK源码

官网提供了两种下载方式:

  1. 通过Mercurial版本控制工具下载(

  2. 通过官网提供的压缩包下载并解压(目前只提供了jdk6的版本):

由于一些版本问题,踩过坑后,笔者毅然采取了第一种方式,下载了jdk7u版本( hg clone ),如果没有安装Mercurial,请先安装一下。

下载好后,可以参考README-builds.html文档,里面有很多需要注意的细节。官方文档称编译jdk需要很高的专业技术,Sun提供了jdk源码是为了技术专家进行研究之用。虽然没有这么夸张,但还是要注意细节。

2. 构建编译环境

  1. 需要安装最新版本的XCode和Command Line Tools for XCode。这两个SDK包提供了OpenJDK所需要的编译器以及Makefile中用到的外部命令。

  2. 需要准备一个6u14以上版本的JDK,因为OpenJDK的各个组成部分有的使用C++编写,更多代码则是使用Java自身实现的,因此编译这些代码需要一个可用的JDK,官方称这个SDK为“Bootstrap JDK”。

3. 进行编译

下面直接贴上Shell脚本,读者可参考注释内容。

#语言选项,这个必须要配置,否则编译后会出现一个Hashtable的NPE错误。
export LANG=C
#Bootstrap JDK的安装路径。
export ALT_BOOTDIR=/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home
#允许自动下载依赖
export ALLOW_DOWNLOAD=true
#并行编译的线程数,设置为和CPU内核数量一致即可,通过 关于本机-系统报告-核总数 可查看
export HOSTPOT_BUILD_JOBS=2
export ALT_PARALLEL_COMPILE_JOBS=2

#比较本次bulid出来的映像和之前版本的差异。这对我们第一次编译来说没有意义
#因此设置为true,否则sanity检查会报缺少先前版本JDK映像的错误提示
export SKIP_COMPARE_IMAGES=true

#使用预编译头文件,不加这个编译会更慢
export USE_PRECOMPILED_HEADER=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=false
#export SKIP_FASTDEBUG=true
#export DEBUG_NAME=debug

#将它设置为fasle,可以避开javawa和浏览器Java插件之类的部分的build
BUILD_DEPLOY=false

#将它设置为false就不会build出安装包,因为安装包里面有奇怪的依赖
#但即使不build它也已经能得到完整的jdk映像了
BUILD_INSTALL=false

#编译结果存放的路径
export ALT_OUTPUTDIR=/Users/wangjun/Downloads

#这两个环境变量必须去掉,不然会有很诡异的事情发生
unset JAVA_HOME
unset CLASSPATH

#先执行make sanity,显示Sanity check passed.成功后再执行make 2>&1 | tee $ALT_OUTPUTDIR/build.log
#make sanity
#make 2>&1 | tee $ALT_OUTPUTDIR/build.log

4. 可能遇到的错误以及解决办法

1. make sanity的时候报错:

   jdk/make/common/shared/Defs-utils.gmk:79: *** "\"ant\" not found; please set ANT_HOME or put \"ant\" on your PATH".  Stop.

解决方案:这个错误是由于忘记安装ant了,安装ant即可

2. make sanity的时候报错:

  ERROR: The Compiler version is undefined. 

  ERROR: FreeType version  2.3.0  or higher is required. 
   /bin/mkdir -p /Users/wangjun/Downloads/jdk7u-dev/build/macosx-x86_64/btbins
  rm -f /Users/wangjun/Downloads/jdk7u-dev/build/macosx-x86_64/btbins/freetype_versioncheck
  Failed to build freetypecheck.  

  Exiting because of the above error(s). 

  make: *** [post-sanity] Error 1

解决方案:

The Compiler version is undefined. 原因是Xcode5.0之后不再提供llvm-gcc与llvm-g++这两样东西,编译jdk是需要这两个所以一直出错。

解决方法是在XCode的安装目录下/Applications/Xcode.app/Contents/Developer/usr/bin 做一个ln -s的链接连到/usr/bin的 llvm-g++ llvm-gcc中

例子:

sudo ln -s /usr/bin/llvm-g++ /Applications/Xcode.app/Contents/Developer/usr/bin/llvm-g++
sudo ln -s /usr/bin/llvm-gcc /Applications/Xcode.app/Contents/Developer/usr/bin/llvm-gcc

FreeType version 2.3.0 or higher is required. 的原因是freetype的版本太低或者没有安装freetype。

使用brew重新安装freetype最新版本:

brew install freetype

然后更新环境变量:

export ALT_FREETYPE_HEADERS_PATH=/usr/local/Cellar/freetype/2.9/include/freetype2

重新make sanity就可以了。

3. 编译时报错

BUILD FAILED
/Users/wangjun/Downloads/jdk7u-dev/langtools/make/build.xml:452: The following error occurred while executing this line:
/Users/wangjun/Downloads/jdk7u-dev/langtools/make/build.xml:795: Compile failed; see the compiler error output for details.

解决方案:

安装jdk7版本,并更新

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

4. 编译时报错

jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:3217:71: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality]
    if ( ((primary = get_ident_or_literal_constant("primary opcode")) == NULL) ) {
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
/Users/wangjun/Downloads/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:3226:77: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality]
      if ( ((secondary = get_ident_or_literal_constant("secondary opcode")) == NULL) ) {
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
/Users/wangjun/Downloads/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:3235:77: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality]
        if ( ((tertiary = get_ident_or_literal_constant("tertiary opcode")) == NULL) ) {
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
/Users/wangjun/Downloads/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:4476:21: error: '&&' within '||' [-Werror,-Wlogical-op-parentheses]
  while ((c >= '0') && (c <= '9')
         ~~~~~~~~~~~^~~~~~~~~~~~~
/Users/wangjun/Downloads/jdk7u-dev/hotspot/src/share/vm/adlc/adlparse.cpp:4515:17: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality]
    if( (second == '=') ) {
         ~~~~~~~^~~~~~
5 errors generated.

解决方案:

因为一开始没有在环境变量面去设置,所以要在环境变量里面加上

#解决严格检查导致的错误
export COMPILER_WARNINGS_FATAL=false

5. 编译时报错

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

解决方案:

clang不支持参数-fpch-deps

首先查到哪个文件用到了

find . -type f ! -name "*.java" | xargs grep -r "\-fpch\-deps"

./hotspot/make/bsd/makefiles/gcc.make:DEPFLAGS = -fpch-deps -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
./hotspot/make/linux/makefiles/gcc.make:DEPFLAGS = -fpch-deps -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
./hotspot/make/solaris/makefiles/gcc.make:DEPFLAGS = -fpch-deps -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
Binary file ./hotspot/.hg/store/data/make/bsd/makefiles/gcc.make.i matches
Binary file ./hotspot/.hg/store/data/make/linux/makefiles/gcc.make.i matches
Binary file ./hotspot/.hg/store/data/make/solaris/makefiles/gcc.make.i matches

#在网上搜到的答案都是,Mac选择bsd,修改./hotspot/make/bsd/makefiles/gcc.make
1)注释217-219行
# Flags for generating make dependency flags.
# ifneq ("${CC_VER_MAJOR}", "2")
# DEPFLAGS = -fpch-deps -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
# endif
2)在219行下添加下面代码
DEPFLAGS = -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
ifeq ($(USE_CLANG),)
  ifneq ($(CC_VER_MAJOR), 2)
    DEPFLAGS += -fpch-deps
  endif
endif

##发现还是报错,后来干脆都注释了,虽然不知道这个参数的作用是啥
DEPFLAGS = -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
#ifeq ($(USE_CLANG),)
#  ifneq ($(CC_VER_MAJOR), 2)
#    DEPFLAGS += -fpch-deps
#  endif
#endif

6. 编译失败,形参默认值问题

报错

/Users/wangjun/Downloads/jdk7u-dev/hotspot/src/share/vm/code/relocInfo.hpp:469:18: error: friend
      declaration specifying a default argument must be the only declaration
inline relocInfo prefix_relocInfo(int datalen) {
                 ^
/Users/wangjun/Downloads/jdk7u-dev/hotspot/src/share/vm/code/relocInfo.hpp:374:27: note: previous
      declaration is here
  inline friend relocInfo prefix_relocInfo(int datalen = 0);
                          ^
/Users/wangjun/Downloads/jdk7u-dev/hotspot/src/share/vm/code/relocInfo.hpp:471:59: error: 'RAW_BITS' is a
      protected member of 'relocInfo'
  return relocInfo(relocInfo::data_prefix_tag, relocInfo::RAW_BITS, relocInfo::datalen_tag | datalen);
                                                          ^
/Users/wangjun/Downloads/jdk7u-dev/hotspot/src/share/vm/code/relocInfo.hpp:279:23: note: declared
      protected here
  enum RawBitsToken { RAW_BITS };
                      ^
/Users/wangjun/Downloads/jdk7u-dev/hotspot/src/share/vm/code/relocInfo.hpp:471:10: error: calling a
      protected constructor of class 'relocInfo'
  return relocInfo(relocInfo::data_prefix_tag, relocInfo::RAW_BITS, relocInfo::datalen_tag | datalen);
         ^
/Users/wangjun/Downloads/jdk7u-dev/hotspot/src/share/vm/code/relocInfo.hpp:280:3: note: declared
      protected here
  relocInfo(relocType type, RawBitsToken ignore, int bits)
  ^

解决方法

# 解决办法
# 修改relocInfo.hpp(路径:hotspot/src/share/vm/code/relocInfo.hpp)
修改374行
inline friend relocInfo prefix_relocInfo(int datalen);
修改469行
inline relocInfo prefix_relocInfo(int datalen = 0) {
   assert(relocInfo::fits_into_immediate(datalen), "datalen in limits");
   return relocInfo(relocInfo::data_prefix_tag, relocInfo::RAW_BITS, relocInfo::datalen_tag | datalen);
}

7. 编译失败

/Users/wangjun/Downloads/jdk7u-dev/hotspot/src/share/vm/runtime/virtualspace.cpp:527:14: error: ordered
      comparison between pointer and zero ('char *' and 'int')
  if (base() > 0) {
      ~~~~~~ ^ ~
/Users/wangjun/Downloads/jdk7u-dev/hotspot/src/share/vm/runtime/virtualspace.cpp:545:23: warning: 
      implicit conversion changes signedness: 'int' to 'size_t' (aka 'unsigned long') [-Wsign-conversion]
                  lcm(os::vm_page_size(), prefix_align) : 0) {
                  ~~~ ^~~~~~~~~~~~~~~~~~
/Users/wangjun/Downloads/jdk7u-dev/hotspot/src/share/vm/runtime/virtualspace.cpp:546:14: error: ordered
      comparison between pointer and zero ('char *' and 'int')
  if (base() > 0) {
      ~~~~~~ ^ ~

解决方案:

jdk7u-dev/hotspot/src/share/vm/runtime/virtualspace.cpp文件
527行改成
if (base() != NULL) {
546行改成
if (base() != NULL) {

8.编译失败,找不到对应的类库和方法

cd bsd_amd64_compiler2/product && ./test_gamma
Using java runtime at: /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/jre
Error occurred during initialization of VM
Unable to load native library: dlopen(/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/jre/lib/libjava.dylib, 1): Symbol not found: __cg_jpeg_resync_to_restart
  Referenced from: /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib
  Expected in: /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/jre/lib/libJPEG.dylib
 in /System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib

解决方案:

将

/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources

下面的libJPEG.dylib拷贝到

/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/jre/lib

下面,覆盖掉之前的libjpeg.dylib。

9.编译失败,

../../../src/solaris/native/sun/awt/utility/rect.h:31:10: fatal error: 'X11/Xlib.h' file not found
#include <X11/Xlib.h>
         ^~~~~~~~~~~~
1 error generated.
make[5]: *** [/Users/wangjun/Downloads/myjdk7/tmp/sun/sun.awt/awt/obj64/Region.o] Error 1
make[5]: *** Waiting for unfinished jobs....
In file included from ../../../src/share/native/sun/awt/image/BufImgSurfaceData.c:31:
In file included from ../../../src/solaris/native/sun/awt/img_util_md.h:26:
In file included from ../../../src/solaris/native/sun/awt/color.h:28:
../../../src/solaris/native/sun/awt/awt.h:38:10: fatal error: 'X11/Intrinsic.h' file not found
#include <X11/Intrinsic.h>
         ^~~~~~~~~~~~~~~~~
1 error generated.

解决方案:

http://hg.openjdk.java.net/);
http://download.java.net/openjdk/jdk6。
http://hg.openjdk.java.net/jdk7u/jdk7u-dev/