一、前言

最近在看《深入java虚拟机》,看完后,打算自己实际编译一个jvm出来看看,实践一下。

书上提到了Oracle JDK和OpenJdk的关系,Oracle Jdk7 和OpenJdk 7共用了相当多的代码,所以还是很有学习的必要的:

二、环境

我这里的编译的操作系统是CentOS Linux release 7.4.1708 (Core)  (通过 cat /etc/centos-release查看)。

编译环境相当重要,因为编译openjdk的过程中,网上的文章里,大家遇到的各个问题都不一样,就是因为操作系统不一致。

我主要参考了某位园友的博客:https://www.cnblogs.com/gotodsp/p/8975387.html

该博客里有他用到的工具的百度网盘链接。大家可自行下载。我是下载了之后,通过centos中安装的lrzsz命令来上传的。

命令为rz(上传),sz(下载)。

没安装的话,执行 yum install lrzsz

下面是另一个参考的博客:

http://blog.51cto.com/wangyahui/1612838

我这里引用了不少原博客的内容,但是中间还是有很多问题。我这里会补充说明。

2.1 卸载原jdk

rpm -qa | grep java

yum -y remove XXXX   --XXXX是第一条命令查出来的jdk信息

2.2 编译相关的工具

yum -y install gcc gcc-c++ alsa-lib alsa-lib-devel libXrender libXrender-devel libXi-devel libXt-devel libXtst-devel cups cups-devel

2.3 FreeType

注意:我这边,会把所有工具,最后都解压到/usr/local目录下。先上一张我最后成功了的图:

tar -zxvf freetype-2.4.0.tar.gz -C /usr/local

cd /usr/local/freetype-2.4.0

./configure && make && make install    # 编译安装

##注意:如果安装中出现以下错误

rmdir /usr/local/include/freetype2/freetype/internal 
rmdir: failed to remove `/usr/local/include/freetype2/freetype/internal': No such file or directory 
make: [install] Error 1 (ignored) 
/usr/bin/install -c -m 644 ./builds/unix/ft2unix.h \ 
/usr/local/include/ft2build.h 
/usr/bin/install -c -m 644 ./builds/unix/ftconfig.h \ 
/usr/local/include/freetype2/freetype/config/ftconfig.h

执行以下命令处理:

mkdir -p /usr/local/include/freetype2/freetype/internal

重新安装

./configure && make && make install

2.4 Apache Ant

tar -zxvf apache-ant-1.9.7-bin.tar.gz -C /usr/local # 解压

ln -s /usr/local/apache-ant-1.9.7/bin/ant /usr/bin/ant  # 软链接到bin

2.5 BootstrapJDK

上传到你的虚拟机上后,

chmod +x jdk-6u45-linux-x64.bin

./jdk-6u45-linux-x64.bin    # 解压

mv jdk1.6.0_45 /usr/local/  # 移动目录

然后 vim /etc/profile,配置:

#java environment
export JAVA_HOME=/usr/local/jdk1.6.0_45
export CLASSPATH=.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar
export PATH=$PATH:${JAVA_HOME}/bin

然后执行 source /etc/profile.

再执行java -version试试,看看是不是生效。

2.6 OpenJdk

unzip openjdk-7-fcs-src-b147-27_jun_2011.zip   # 解压

原文章中说得有点乱,不管怎样,做成下面我这种目录效果就行:

三、准备环境变量

vim /etc/profile #在末尾加以下内容。注意其中的目录的路径,另外,先不要忙着执行,先把这一节看完:

export ANT_HOME=/usr/local/apache-ant-1.9.7

export ALT_FREETYPE_HEADERS_PATH=/usr/local/include/freetype2
export ALT_FREETYPE_LIB_PATH=/usr/local/lib
export ALT_DROPS_DIR=/usr/local/src/openjdk/drop
export ALT_BOOTDIR=/usr/local/jdk1.6.0_45
export ALT_JDK_IMPORT_PATH=/usr/local/jdk1.6.0_45
export ALT_OUTPUTDIR=/usr/local/openjdk_output
export LANG=C
export HOTSPOT_BUILD_JOBS=8
export ALT_PARALLEL_COMPILE_JOBS=8
export SKIP_COMPARE_IMAGES=true
export USE_PRECOMPILED_HEADER=true
export ALLOW_DOWNLOADS=true
export SKIP_DEBUG_BUILD=false
export SKIP_FASTDEBUG_BUILD=true
export DEBUG_NAME=debug
export BUILD_LANGTOOLS=true
export BUILD_HOTSPOT=true
export BUILD_JDK=true
export BUILD_DEPLOY=false
export BUILD_INSTALL=false
unset JAVA_HOME
unset CLASSPATH
unset LD_LIBRARY_PATH

这里依次解释下各个选项:

  • ANT_HOME   # 编译工具ant的路径
  • ALT_FREETYPE_HEADERS_PATH  #  freetype2头文件安装目录,一般无需替换
  • ALT_FREETYPE_LIB_PATH # 这个也无需修改
  • ALT_DROPS_DIR #这个目录很重要,下图来自参考的那位园友的博客里的:

  • ALT_BOOTDIR  #启动jdk的路径
  • ALT_JDK_IMPORT_PATH #看文章里是配成一致的,暂时还不知道配成不一致的结果
  • ALT_OUTPUTDIR  #最终编译输出的位置,来个直观图展示下

  

  • LANG  ##语言选项,这个必须设置,否则编译好后会出现一个HashTable的NPE错
  • HOTSPOT_BUILD_JOBS #并行编译的线程数,设置为和CPU内核数量一致即可
  • ALT_PARALLEL_COMPILE_JOBS #并行编译的线程数,设置为和CPU内核数量一致即可
  • SKIP_COMPARE_IMAGES  #比较本次build出来的映像与先前版本的差异。这对我们来说没有意义,必须设置为true,否则sanity检查会报缺少先前版本JDK的映像的错误提示。
  • USE_PRECOMPILED_HEADER #使用预编译头文件,不加这个编译会更慢一些
  • ALLOW_DOWNLOADS  #允许自行下载依赖
  • SKIP_DEBUG_BUILD  #要编译的版本
  • SKIP_FASTDEBUG_BUILD 要编译的版本
  • BUILD_LANGTOOLS # 是否编译语言工具
  • BUILD_HOTSPOT #编译虚拟机
  • BUILD_JDK 编译jdk
  • BUILD_DEPLOY #把它设置为false可以避开javaws和浏览器Java插件之类的部分的build
  • BUILD_INSTALL #把它设置为false就不会build出安装包。因为安装包里有些奇怪的依赖,但即便不build出它也已经能得到完整的JDK映像,所以还是别build它好了

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

设置完了后,保存,刷新一下。 source /etc/profile

四、检查

在/usr/local/src/openjdk下运行 make sanity。

如果最后一行显示:

Sanity check passed.

则表示检查通过。

五、编译jvm

在同上目录下,执行 make DISABLE_HOTSPOT_OS_VERSION_CHECK=ok

之所以加DISABLE_HOTSPOT_OS_VERSION_CHECK=ok,是因为遇到了下面的异常:

ERROR:××× recipe for target ‘check_os_version’ failed ×××

为了跳过版本校验,所以加了上述参数。

参考了:https://blog.csdn.net/desiyonan/article/details/80801830

好了,接下来静静等待,我最后那一次成功的编译,花了大概20-30分钟,成功了,会有如下显示(突然发现前面tree了一把,刷屏了,只能网上去找个图了。。。):

(别人家怎么那么快,10分钟。。。)

我这边还是贴一个我这边编译好的虚拟机的version显示吧:

如果你没那么幸运,发生了各种error,导致make中断的话,不要走开。参考下面一节。

六、遇到的问题

ps:如果看到提示某个文件报错,又不知道在哪,大家直接用find / -name abc.txt查找吧。

1、Error: time is more than 10 years from present: 1136059200000

通过修改CurrencyData.properties文件, 把10年之前的时间修改为10年之内即可
Index: /usr/openjdk/jdk/src/share/classes/java/util/CurrencyData.properties

注意,该文件内有5,6处要修改的地方。不要漏了,漏了又是10+分钟。。

2、 /usr/bin/ld: cannot find -lstdc++

Linking vm...
/usr/bin/ld: cannot find -lstdc++
collect2: error: ld returned 1 exit status
/usr/bin/chcon: cannot access 'libjvm.so': No such file or directory
ERROR: Cannot chcon libjvm.so
/usr/bin/objcopy --only-keep-debug libjvm.so libjvm.debuginfo
/usr/bin/objcopy: 'libjvm.so': No such file
make[4]: *** [libjvm.so] Error 1
make[4]: Leaving directory `/usr/src/openjdk/hotspot/build/hotspot_debug/linux_amd64_compiler2/debug'
make[3]: *** [the_vm] Error 2
make[3]: Leaving directory `/usr/src/openjdk/hotspot/build/hotspot_debug/linux_amd64_compiler2/debug'
make[2]: *** [debug] Error 2
make[2]: Leaving directory `/usr/src/openjdk/hotspot/build/hotspot_debug'
make[1]: *** [generic_build2] Error 2
make[1]: Leaving directory `/usr/src/openjdk/hotspot/make'
make: *** [debug] Error 2


解决:

yum search libc++ 
yum install libstdc++-static

3、不识别'-mimpure-text'参数

报错:gcc: error: unrecognized command line option '-mimpure-text'

make[5]: *** [/openjdk/build/linux-amd64/../linux-amd64-debug/lib/amd64/libverify.so] Error 1

解决:

就在 openjdk源码中的,/make/common/shared/Compiler-gcc.gmk 中去掉 -mimpure-text 命令

4、constantPoolOop.cpp

Error:/openjdk/hotspot/src/share/vm/oops/constantPoolOop.cpp:272:39: error: converting 'false' to pointer type 'methodOop' [-Werror=conversion-null]

将return false 改为return NULL

5、__LEAF 头文件重复定义问题

/openjdk/hotspot/src/share/vm/runtime/interfaceSupport.hpp:430:0: error: "__LEAF" redefined [-Werror]
 #define __LEAF(result_type, header)

/usr/include/x86_64-linux-gnu/sys/cdefs.h:42:0: note: this is the location of the previous definition
 #  define __LEAF , __leaf__

在interfaceSupport.hpp代码的最前面增加:(后面的\也是需要的,宏定义中的换行符)

#ifdef __LEAF
#undef __LEAF

#define __LEAF(result_type, header)                                  \
  TRACE_CALL(result_type, header)                                    \
  debug_only(NoHandleMark __hm;)                                     \
  /* begin of body */
#endif

6、/hotspot/src/share/vm/opto/loopnode.cpp:896:49: error: converting 'fals' to pointer type 'Node*' [-Werror=conversion-null]

解决:修改openjdk/hotspot/src/share/vm/opto/loopnode.cpp: 第896行 return false改为return (Node*)false; 或者 return NULL;

7、无法下载包问题 Redirection detected from https to http. Protocol switch unsafe, not allowed

解决:其实前面已经提到了,网盘里提供了jdk6-jaf-b20.zip、jdk6-jaxp-b20.zip、jdk6-jaxws-b20.zip三个文件即为了解决该问题。将这三个文件复制到openjdk/drop目录下。

同时要配置ALT_DROPS_DIR指向该目录。

七、总结

今天搞这个+写博客,差不多大半天了。。。

一千个人编译jdk,就会有一千个错误。。。

关键是等得又久,错了又得重来。。。不过再怎么说,还是很有成就感的。

看了书,就得实践,毕竟老祖宗说的:纸上得来终觉浅,绝知此事要躬行。

编译你的第一个Java虚拟机--Centos 7 编译openJdk1.7源码的更多相关文章

  1. 深入理解Java虚拟机(程序编译与代码优化)

    文章首发于微信公众号:BaronTalk,欢迎关注! 对于性能和效率的追求一直是程序开发中永恒不变的宗旨,除了我们自己在编码过程中要充分考虑代码的性能和效率,虚拟机在编译阶段也会对代码进行优化.本文就 ...

  2. java开源即时通讯软件服务端openfire源码构建

    java开源即时通讯软件服务端openfire源码构建 本文使用最新的openfire主干代码为例,讲解了如何搭建一个openfire开源开发环境,正在实现自己写java聊天软件: 编译环境搭建 调试 ...

  3. Java 集合系列 09 HashMap详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  4. Java 集合系列 10 Hashtable详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  5. Java 集合系列 06 Stack详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  6. Java 集合系列 05 Vector详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  7. Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  8. Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  9. java 日志体系(四)log4j 源码分析

    java 日志体系(四)log4j 源码分析 logback.log4j2.jul 都是在 log4j 的基础上扩展的,其实现的逻辑都差不多,下面以 log4j 为例剖析一下日志框架的基本组件. 一. ...

随机推荐

  1. Intellij IDEA 自动清除无效 import 和 清除无效 import 的快捷键 ctrl+alt+o

    快捷键 ctrl+alt+o 自动清除的配置方法 可以settings-general-auto import-java项,勾选optimize imports on the fly,在当前项目下会自 ...

  2. 微软BI 之SSIS 系列 - Execute SQL Task 中的 Single Row 与 Full Result Set 的处理技巧

    开篇介绍 Execute SQL Task 这个控件在微软BI ETL 项目中使用的频率还是非常高的,也是大部分入门 SSIS 初学者最早接触到的几个控制流控件. 我们通常使用 Execute SQL ...

  3. postgresql 函数获取多个字段的数字大小值

    1.GREATEST(n1,n2,n3,..........) 获取最大值 testdb=#SELECT GREATEST(,,,,,,,,,); +------------------------- ...

  4. Spark机器学习(9):FPGrowth算法

    关联规则挖掘最典型的例子是购物篮分析,通过分析可以知道哪些商品经常被一起购买,从而可以改进商品货架的布局. 1. 基本概念 首先,介绍一些基本概念. (1) 关联规则:用于表示数据内隐含的关联性,一般 ...

  5. CAP Twelve Years Later: How the "Rules" Have Changed

    The CAP theorem asserts that any net­worked shared-data system can have only two of three desirable ...

  6. 百度「Web 前端研发部」面试过程和常见问题 可能会采用哪些方法来面试 STAR 面试法 喜欢什么样的面试者 喜欢问的问题

    http://segmentfault.com/a/1190000002498800 在他们的github上看到的,收藏一下备用.看完觉得还有很多要努力的地方. FEX 的面试过程 我们一般会有 3 ...

  7. 【C语言】字节对齐问题(以32位系统为例)

    1. 什么是对齐? 现代计算机中内存空间都是按照字节(byte)划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型 ...

  8. 将R非时间序列的data.frame转变为时序格式

    将R非时间序列的data.frame转变为时序格式,常常会用到,尤其是股票数据处理中, 举例:dailyData包括两列数据:Date Close10/11/2013 871.9910/10/2013 ...

  9. loadrunner 关联匹配多个值

    loadrunner 关联获取从服务器返回相关值,如果需要把所有匹配的值都获取并且把这些值打印出来,怎么做呢? 1.首先要把把所有的匹配值都保存起来,需要在关联函数里面多传递一个参数:"Or ...

  10. 【Spark 深入学习 07】RDD编程之旅基础篇03-键值对RDD

    --------------------- 本节内容: · 键值对RDD出现背景 · 键值对RDD转化操作实例 · 键值对RDD行动操作实例 · 键值对RDD数据分区 · 参考资料 --------- ...