一、前言

最近在看《深入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. Spark2.3(三十七):Stream join Stream(res文件每天更新一份)

    kafka测试数据生成: package com.dx.kafka; import java.util.Properties; import java.util.Random; import org. ...

  2. 马斯克:有62%的程序员认为人工智能会被武器化 #精选AR人工智能算法

    当地时间 9 月 13 日,马斯克在自己的个人推特账号上转推了一篇名为<Hackers Have Already Started to Weaponize Artificial Intellig ...

  3. wifipineapple获取用户上网信息

    ssh连接到wifipineapple: 输入连接信息:ssh root@172.16.42.1 输入密码:pineapplesareyummy 安装依赖基本环境: opkg update opkg ...

  4. 解决 Docker pull 出现的net/http: TLS handshake timeout 的一个办法

    echo "DOCKER_OPTS=\"\$DOCKER_OPTS --registry-mirror=http://f2d6cb40.m.daocloud.io\"&q ...

  5. 使用yocs_velocity_smoother对机器人速度进行限制

    yocs_velocity_smoother是一个速度.加速度限制器,用来防止robot navigation的速度/转速过快,加速度/快减速过大.Bound incoming velocity me ...

  6. 10个优秀Objective-C和iOS开发在线视频教程

    如果你自己开发iOS应用,你肯定会发现网上有很多资源.学习编程的一个最好的方法就是自己写代码,而开始写代码的最快的方式就是看其他人怎么写.我们从海量视频和学习网站中整理出了我们认为对你学习Object ...

  7. 你可能不知道的51个Linux经典命令

    1.删除0字节文件 代码如下: find -type f -size 0 -exec rm -rf {} \; 2.查看进程按内存从大到小排列 代码如下: ps -e -o "%C : %p ...

  8. mariadb(MySql)设置远程访问权限

    [问题]mariadb(MySql)安装之后,本地连接mysql是可以的,但是远程的机器不能连接和访问. [解决]修改mysql远程连接的ip限制配置. [步骤]1.本地mysql客户端连接mysql ...

  9. mac无法访问samba共享 提示输入用户名密码

    这时候需要输入mac笔记本的用户名和密码 也可以在samba服务器上增加用用户: # smbpasswd -a user_nameNew SMB password:Retype new SMB pas ...

  10. 菜鸟教程之工具使用(八)——EGit禁止自动转换回车换行符

    众所周知,Windows和Linux系统的回车换行是不一样的.想要进一步了解它们的可以阅读下面的介绍,不感兴趣的可以直接跳过. 产生背景 关于“回车”(carriage return)和“换行”(li ...