前言:
java是一门深受大家欢迎的语言,其最大的优点是其jvm虚拟机封装了便捷的内存管理机制以及垃圾收集策略,这一部分也正是java的核心部分。要想了解其工作原理,我们必须下载jvm的源码,对其编译。源码我们可以使用开源的openjdk,openjdk与Oracle的jdk差别很小。环境最好使用Linux或者Mac OS。接下来我记录了自己在Linux上编译openjdk的过程以及期间遇到的问题和解决方法,拿出来和大家分享。
环境信息:CentOS 6.5(64位)
系统jdk:jdk 1.7_80(64位),请自行去官网下载
编译jdk:Openjdk 1.7_40(64位),请自行去openjdk官网下载
相关软件:freetype-2.3.12.tar.gz 下载地址:http://sourceforge.net/projects/freetype/files/freetype2/
apache-ant-1.7.1-bin.zip 下载地址:http://archive.apache.org/dist/ant/binaries/
一、准备工作
1.安装jdk1.7到CentOS系统,设置系统变量,在此不细述
安装完成后使用java -version检查
2.上传openjdk1.7压缩包,解压至相应目录
3.解压freetype,编译安装:
tar -xzf freetype-2.3.12.tar.gz cd freetype-2.3.12 ./configure make make install
4.安装ant:
cd /application/tools/ unzip apache-ant-1.7.1-bin.zip ln -s /application/tools/apache-ant-1.7.1/bin/ant /usr/bin/ant
5.安装其余关联软件包:
yum -y install alsa-lib-devel yum -y install cups-devel yum -y install libXi-devel yum -y install gcc gcc-c++ yum -y install libX*
二、配置编译环境变量
修改.bash_profile文件,添加以下环境信息,摘自《深入理解jvm虚拟机》
#语言选项,这个必须设置,否则编译好后会出现一个HashTable的NPE错
export LANG=C
#Bootstrap JDK的安装路径。必须设置
export ALT_BOOTDIR=/Library/Java/JavaVirtualMachines/jdk1.7.0_04.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 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
export BUILD_DEPLOY=false
#把它设置为false就不会build出安装包。因为安装包里有些奇怪的依赖,
#但即便不build出它也已经能得到完整的JDK映像,所以还是别build它好了
export BUILD_INSTALL=false
#编译结果所存放的路径
export ALT_OUTPUTDIR=/Users/IcyFenix/Develop/JVM/jdkBuild/openjdk_7u4/build
#这两个环境变量必须去掉,不然会有很诡异的事情发生(我没有具体查过这些"诡异的
#事情",Makefile脚本检查到有这2个变量就会提示警告)
unset JAVA_HOME
unset CLASSPATH
三、环境变量检查
执行
[jvm@localhost openjdk]# make sanity
进行makefile的sanity检查,若是看到sanity check passed就说明环境变量检查通过了,如果出错,请根据报错信息对照上述步骤进行检查,一般是误操作导致哪里配错了或者遗漏。
四、编译
执行
[jvm@localhost openjdk]# make
编译的时间可能持续十几分钟,期间遇到错误会停止,若出现
>>>Finished making images @ Wed Dec 21 01:00:35 PST 2016 ...
make[2]: Leaving directory `/home/jvm/jdk/openjdk/jdk/make'
########################################################################
##### Leaving jdk for target(s) sanity all docs images #####
########################################################################
##### Build time 00:08:11 jdk for target(s) sanity all docs images #####
########################################################################
#-- Build times ----------
Target all_product_build
Start 2016-12-21 00:52:08
End 2016-12-21 01:00:35
00:00:04 corba
00:00:05 hotspot
00:00:02 jaxp
00:00:03 jaxws
00:08:11 jdk
00:00:02 langtools
00:08:27 TOTAL
-------------------------
make[1]: Leaving directory `/home/jvm/jdk/openjdk'
则代表编译成功了,下面再列出我编译过程中遇到的问题,以及解决办法
五、编译常见错误及解决
make[6]: Entering directory `/home/jvm/jdkbuild/build/hotspot/outputdir/linux_amd64_compiler2/product'
echo "**NOTICE** Dtrace support disabled: "/usr/include/sys/sdt.h not found""
**NOTICE** Dtrace support disabled: /usr/include/sys/sdt.h not found
make[6]: Leaving directory `/home/jvm/jdkbuild/build/hotspot/outputdir/linux_amd64_compiler2/product'
All done.
make[5]: Leaving directory `/home/jvm/jdkbuild/build/hotspot/outputdir/linux_amd64_compiler2/product'
cd linux_amd64_compiler2/product && ./test_gamma
Using java runtime at: /usr/java/jdk1.7.0_80/jre
./gamma: relocation error: /usr/java/jdk1.7.0_80/jre/lib/amd64/libjava.so: symbol JVM_FindClassFromCaller, version SUNWprivate_1.1 not defined in file libjvm.so with link time reference
据说这是OpenJDK 和 Oracle JDK 版本冲突引起的 BUG,经过多种方法的尝试后,确定一种方法有效:
2.报错信息
Error: time is more than 10 years from present: 1136059200000
java.lang.RuntimeException: time is more than 10 years from present: 1136059200000
at build.tools.generatecurrencydata.GenerateCurrencyData.makeSpecialCaseEntry(GenerateCurrencyData.java:285)
at build.tools.generatecurrencydata.GenerateCurrencyData.buildMainAndSpecialCaseTables(GenerateCurrencyData.java:225)
at build.tools.generatecurrencydata.GenerateCurrencyData.main(GenerateCurrencyData.java:154)
make[4]: *** [/home/jvm/jdkbuild/build/lib/currency.data] Error 1
./jdk/src/share/classes/java/util/CurrencyData.properties
通过修改/jdk/src/share/classes/java/util/CurrencyData.properties文件, 把10年之前的时间修改为10年之内即可(把所有的时间格式的时间改为2015以前的十年以内的年数)例如:
# VENEZUELA
VE=VEB;2014-12-22-20-00-00;VEF
注意日期要小于2015年,前在十年之内,原日期可能超出十年了