ubuntu编译hotspot源码实践

  • tags:hotspot
  • categories:笔记
  • date: 2017-03-08 13:13:51
最近看了不少jdk源代码和JVM相关知识,虽然有很多东西不是一次可以看懂的,理解的。但是可以多看几次,多模仿与实践,对于自己编码和理解来说,总是没多大坏处的吧。最近有时间,又想把《hotspot实战》看看,这些书籍似乎都是很多人强力推荐的啊(╯▔^▔)╯。。话说,逼格也高啊。不知道是不是那么神,所以,我要亲身实践看看,嘿嘿。第一次也许理解不是那么深,当自己代码量上来了,也许想起这些东西,就会有醍醐灌顶的感觉呢。乘着自己有时间,就像多看看,多接近底层,多贴近0与1。应该更能理解计算机这位"佳人"吧,哈哈....

ubuntu编译hotspot源码实践
文章图片
hotspot_achitecture.jpg
主要还是参考《hotspot实战》这本书进行的,但是根据自己不同的系统环境与基础资源,编译工程总会是不那么顺畅的。应为很多都是C/C++库文件,相对于java来说,是偏向底层的,与系统平台的相关的库都会有引用调用等,出现了问题一开始真的会懵逼的( > c < ) 。不过,宝宝不虚,没点折腾精神还敢说自己是搞IT的码农?are you fucking kidding me ??(/≧▽≦/).........
所以以下是我自己在参考书籍的前提下,依据自己在编译过程中遇到的问题来总结记录下咯。顺便把编译好的文件可以share出来,可以让自己或者其他人按需要使用啦。毕竟也是一路踩着小坑过来的。。。。╮(╯▽╰)╭
编译平台搭建 在这里,因为经常使用vmware,所以就安装ubuntu14在vmware虚拟机上。就打算在虚拟机上编译hotspot。这里需要准备的平台环境包括:
  • vmware虚拟机
    在window上,非常好的虚拟机软件啊。大赞啊,可以创建许多不同系统的虚拟机。在此我使用的是12版本。这里是用来安装ubuntu系统的。这里多说一句,建议将该虚拟机的cpu和处理线程稍微高一些,因为是要进行编译计算处理的,不然会卡的。官网
  • ubuntu系统
    因为实战这本书使用的是ubuntu12的版本,我觉得有点老的,所以使用ubuntu14版本。最好安装desktop桌面版,对于不熟悉shell编程的可以更方便。可以自行度娘啦下载...
然后当然就是在vmware上安装好这个ubuntu14系统啦,可以使用NAT网络连接方式,也就是能让虚拟机可以联网就行。因为后面编译需要联网下载一些其他的运行库。
编译文件准备 在上面的平台环境准备好了,也就是工具都准备好了。剩下的当然就是需要原料啦。主要包括openjdk源码,jdk,ant安装。
  • 下载openjdk源代码
    这个是官方开源的非常好的东西啊,openjdk源代码。MD每天看看源代码,是不是都能成扫地僧啊...( ̄▽ ̄)~.。可以在这里下载:官网百度云-openjdk
  • 安装jdk
    编译当然少不了jdk,可以下载1.6或者1.7的,简易可以不用1.8的,太新也不好。毕竟1.8版本更新不少东西。下载的当然是linux的版本的。可以在这里下载。百度云-jdk64-linux百度云-jdk32-linux
    下载好了,就可以和openjdk一起复制到虚拟机上。至于在linux上安装jdk也是非常简单的,网上也有很多教程,这里简单提一下:
    A. 将.gz结尾的jdk文件拷贝到虚拟机内。eg:我拷贝到desktop后,切换root,在/usr/lib/目录下创建java文件夹,然后将该文件解压:
# cd /usr/lib # mkdir java # exit ~ cd Desktop ~ cp jdk-7u40-linu-x64.tar.gz /usr/lib/java ~ cd /usr/lib/java ~ tar -zxvf jdk-7u40-linu-x64.tar.gz(解压出jdk1.7.0_40文件夹,这就是java的JAVA_HOME) ~ cd jdk1.7.0_40 ~ pwd /usr/lib/java/jdk1.7.0_40

B. 配置java到PATH环境变量
编辑~/.bashrc文件,使用export将java目录设置。
~ vim ~/.bashrc ##在bashrc文件最后添加: export JAVA_HOME=/usr/lib/java/jdk1.7.0_40 export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:$PATH ##选择切换root,也在同样文件下添加环境变量

在编辑文件完之后,使用如下命令,使得该文件立即生效:
~ source ~/.bashrc

C. 验证jdk安装
在shell中,使用命令java -version,当看到版本信息就安装成功了。
  • 安装ant
    因为以前maven还为出现,项目管理都是使用ant管理的,所以我们还需要安装ant。可以在这里下载:百度云-ant-linux ,在下载之后,就进行配置。配置过程和jdk一样的,哎很简单,还是说说吧...
    A. 安装ant
# cd /usr/lib # mkdir ant # exit ~ cd Desktop ~ cp apache-ant-1.9.9-bin.tar.gz /usr/lib/ant ~ cd /usr/lib/ant ~ tar -zxvf apache-ant-1.9.9-bin.tar.gz ~ cd apache-ant-1.9.9 ~ pwd /usr/lib/ant/apache-ant-1.9.9

B. 配置环境变量:
~ vim ~/.bashrc ##在bashrc文件最后添加: #export ALT_BOOTDIR="/usr/lib/java/jdk1.7.0_40" export ALT_BOOTDIR="/usr/lib/java/jdk1.7.0_25" export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib export ANT_HOME=/usr/lib/ant/apache-ant-1.9.9 export PATH=${JAVA_HOME}/bin:$PATH:${ANT_HOME}/bin

C. 验证ant:出现如下信息表示安装成功.
~ ant -version Apache Ant(TM) version 1.9.9 compiled on February 2 2017

好了,环境平台和相关需要的文件资源都准备好了,可以开始编译过程过程了。 <( ̄︶ ̄)>......
编译实践过程 这个过程就是需要我们动手去编译hotspot源代码啦。这里啊,主要看自己运气啦,选的合适的linux系统,安装好相关库,才会编译成功哦。
编写hotspot编译脚本
我们可以写一个编译脚本来自动化hotspot的编译过程。若是都配置好了,其实编译也不是需要多少时间的。我的hotpost文件夹就是放在桌面Desktop上。
/home/hotspot/Desktop/openjdk/hotspot就是我编译的hotspot文件路径。
在hotspot文件目录下创建一个编译脚本,名字可以自定义,我定义为:compile_hotspot.sh
下面的jdk与ant路径需要根据自己的实际配置,还有PATH路径中一些路径最好可以根据自己linux平台的进行配置。
(我刚开始是使用64位jdk1.7.0_40对应jdk版本进行编译的,但是在最后运行./test_gamma程序时候,提示需要使用32位jdk,所以后面我又将jdk换成了32位的jdk1.7.0_25)。
在编译hotspot阶段,使用32位还是64看自己了,但是最后运行test_gamma程序时候,一定是需要32位的jdk。如何查看jdk是32位还是64的呢?
root@hotspot-virtual-machine:/home/hotspot/Desktop# java -d32 -version java version "1.7.0_25" Java(TM) SE Runtime Environment (build 1.7.0_25-b15) Java HotSpot(TM) Server VM (build 23.25-b01, mixed mode)

那么说明是32位的,若是出现错误,则不是32位的jdk。
compile_hotspot.sh文件内容:
#!/bin/bash export LANG=C ## 导入jdk #export ALT_BOOTDIR="/usr/lib/java/jdk1.7.0_40" export ALT_BOOTDIR="/usr/lib/java/jdk1.7.0_25" export ALT_JDK_IMPORT_PATH="/usr/lib/java/jdk1.7.0_40"## 导入ant export ANT_HOME="/usr/lib/ant/apache-ant-1.9.9"## 导入PATH export PATH="/usr/lib/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/lib/ant/apache-ant-1.9.9:/usr/lib/x86_64-linux-gnu:/usr/lib/gcc/x86_64-linux-gnu/4.8"export HOTSPOT_BUILD_JOBS=5 #输出目录 export ALT_OUTPUTDIR=../build/hotspot_debug ##选择目标版本为jvmg,启动编译hotspot命令 cd make makeDEBUG_BINARIES=true jvmg jvmg1 2>&1 | tee ~/Desktop/openjdk/hotspot/build/hotspot_debug.log

在最后一行make命令的参数DEBUG_BINARIES=true可千万要配置啊,不配置,编译就会有问题,这就是一个坑了。在后面的编译问题也会说说。
编写编译目标
主要是编辑hotspot/make/Makefile文件,对我们的编译目标进行配置,选择debug级别的目标,这样编译成功后,生成的libjvm(Hotspot VM运行库)中包含丰富的调试信息,通过这些信息,调试器可以建立虚拟机运行时与源代码之间的关联哦,这样我们日后就可以进行单步调试了,是不是听不懂,这就对了。我刚开始也是懵逼的。嘿嘿....
编辑make目录下的Makefile文件,可以先将原来的文件备份,使用cp命令。时刻注意备份啊,我发现我已经有备份强迫症了哈哈....
然后我们可以将原来的文件内容对应的改成如下文件中代码所示:
# JDK directory list JDK_DIRS=bin include jre lib demoall:all_product all_fastdebugifdef BUILD_CLIENT_ONLY all_product:product product1 productkernel docs export_product all_fastdebug: fastdebug fastdebug1 fastdebugkernel docs export_fastdebug all_debug:jvmg jvmg1 jvmgkernel docs export_debug else all_product:product1 docs export_product all_fastdebug: fastdebug1 docs export_fastdebug all_debug:jvmg1 docs export_debug endifall_optimized: optimizedoptimized1 optimizedkernel docs export_optimizedallzero:all_productzero all_fastdebugzero all_productzero:productzero docs export_product all_fastdebugzero: fastdebugzero docs export_fastdebug all_debugzero:jvmgzero docs export_debug all_optimizedzero: optimizedzero docs export_optimizedallshark:all_productshark all_fastdebugshark all_productshark:productshark docs export_product all_fastdebugshark: fastdebugshark docs export_fastdebug all_debugshark:jvmgshark docs export_debug all_optimizedshark: optimizedshark docs export_optimized

至于上面的product,fastdebug等信息,可以参考《hotspot实战》书籍,里面说的挺详细的。这样我们就可以运行之前写的编译脚本了。
开始编译
因为我们之前创建的编译脚本,还不是可以运行脚本。我们需要修改它变成可运行状态:chmod 777 compile_hotspot.sh就可以了。
现在,我们就可以开始执行脚本了啊....
~ cd /home/hotspot/openjdk/hotspot ~ ./compile_hotspot.sh .....开始执行编译

编译过程也就花个十几分钟,若是在编译中出现问题,可以看看最后一节的编译遇到的问题,若是没有参考,只能度娘或者google,stackoverflow求大佬了。哈哈
编译成功
在编译成功后,将在hotspot的目录下有个build目录。build目录时整个编译过程的工作空间,该目录下包含了最终的编译目标。也就是包含两个文件夹如下:
hotspot@hotspot-virtual-machine:~/Desktop/openjdk/hotspot/build/hotspot_debug$ ls linux_i486_compiler1linux_i486_compiler2

进入linux_i486_compiler1/jvmg下,执行./test_gamma,若是出现以下信息,就是代表编译成功了:

ubuntu编译hotspot源码实践
文章图片
compile_success.png 编译遇到的问题?
  • 若是出现g++:command not found,那么说明没有安装g++,可以按照如下命令安装:
    可以先查看gcc版本,在根据匹配的版本进行安装。
gcc --version sudo apt-get install g++-version

  • 若是出现This OS is not supported:'-uname -a ; exit 1'错误信息:
    参考实战书籍可知,时默认支持的linux内核版本最高版本位2.6,而我们所用的发行版本可能采用了高于此版本的linux内核,可以使用uname -a命令查看自己ubuntu14使用的内核版本。我的版本是4.4,所以,可以在hotspot/make/linux/Makefile中,查找字符串SUPPORTED_OS_VERSION,然后在该行代码最后添加自己linux系统的内核版本:
SUPPORTED_OS_VERSION = 2.4% 2.5% 2.6% 4.4%

  • 若出现cc1plus: error: the "stabs" debug format cannot be used with pre-compiled headers [-Werror=deprecate],则需要修改编译脚本中make命令:
    因为高版本的gcc不再支持stabs,解决办法:在make命令中加上 DEBUG_BINARIES=true,这就是我一开始在编写编译脚本部分提到的注意的地方。
  • 若出现/usr/include/features.h|374|fatal error: sys/cdefs.h: No such file or directory问题:
    那说明缺少了一些其他的依赖库,解决办法是安装所有g++编译依赖库:
sudo apt-get install g++-multilib

【ubuntu编译hotspot源码实践】若是还有更多问题可以参考《hotspot实战》书籍,或者参考此片文章:定制属于自己的jvm,编译属于自己的jdk

    推荐阅读