[置顶] Linux下编译OpenJDK源码以及在Eclipse中调试Hotspot虚拟机
2017-11-09 22:48
886 查看
1. 安装mercurial
([mɝ’kjʊrɪəl],水银。同Git一样,是一种分布式版本控制器)先更新source.list
sudo apt-get update
安装mercurial
sudo apt-get install mercurial
验证安装成功,hg命令显示帮助信息
hg
2. 下载OpenJDK源码
mercurial仓库:http://hg.openjdk.java.net/hg clone http://hg.openjdk.java.net/jdk7u/jdk7u-dev/ cd jdk7u-dev chmod 755 get_source.sh ./get_source.sh
==OpenJDK源码有以下几个文件夹:hotspot, langtools, corba, jaxws, jaxp, and jdk==
当执行./get_source.sh脚本,每个文件夹都提示exit code 0时,才成功。如有不成功,多执行几次./get_source.sh
3. Linux上构建OpenJDK源码编译环境
以下引自《深入理解Java虚拟机V2》OpenJDK的各个组成部分(Hotspot、JDK API、JAXWS、JAXP、Langtools……)有的是使用C++ 编写的,更多的代码则是使用Java自身实现的,因此编译这些Java代码需要用到一个可用的JDK,官方称这个JDK为“Bootstrap JDK”。如果编译OpenJDK 7, Bootstrap JDK必须使用JDK6 Update 14或之后的版本,。最后需要下载 一个1.7.1以上的Apache Ant,用于执行Java编译代码中的Ant脚本。
Ubuntu中GCC和G++应该是默认安装好的,需要确保版本为4.3以上。
《深入理解Java虚拟机v2》中道,编译OpenJDK 7u4 所需的依赖可以使用以下命令一次安装完成。
sudo apt-get install build-essential gawk m4 openjdk-6-jdk libasoundd2-dev libcups2-dev libxrender-dev xorg< 4000 span class="hljs-attribute">-dev xutils-dev x11proto-print-dev binutils libmotif3 libmotif-dev ant
上面命令在执行时,可能会有一些问题,安装不成功。下面逐一安装。
1 安装gcc、g++、make等
sudo apt-get install build-essential
2 安装ant 1.7以上
sudo apt-get install ant
3 安装XReader
sudo apt-get install libxrender-dev sudo apt-get install xorg-dev
4 安装alsa
sudo apt-get install libasound2-dev
5 Cups
sudo apt-get install libcups2-dev
6 安装Bootstrap JKD
安装jdk6作为Bootstrap JDK
sudo apt-get install openjdk-6-jdk
7 安装零碎的工具包
sudo apt-get install gawk zip libxtst-dev libxi-dev libxt-dev
4. 设置环境变量
《深入理解JVM》中说道,必须设置的只有两个:LANG和ALT_BOOTDIR,前者是设定语言选项,必须设置为:export LANG=C
否则, 在编译结束前的验证阶段会出现一个HashTable内的空指针异常。另外一个ALT_BOOTDIR参数是前面提到的Bootstrap JDK。
另外,如果读者之前设置了JAVA_HOME和CLASSPATH两个环境变量,在编译之前必须取消,否则在Makefile脚本中检查到有这两个变量存在,会有警告提示。
unset JAVA_HOME unset CLASSPATH
以下是根据《深入理解JVM》结合自己电脑编写的build.sh脚本:
#使用系统/bin/bash解释器(即Shell)执行该脚本 #!/bin/bash #设置语言 export LANG=C export ALT_BOOTDIR=/usr/lib/jvm/jdk1.7.0_75 export JDK_IMPORT_PATH=/usr/lib/jvm/jdk1.7.0_75 #允许自动下载依赖包 export ALLOW_DOWNLOADS=true export SKIP_COMPARE_IMAGES=true #使用预编译头文件,不加这个编译会更慢 export USE_PRECOMPILED_HEADER=true #要编译的内容 export BUILD_LANGTOOLS=true export BUILD_JAXP=true export BUILD_JAXWS=true export BUILD_CORBA=true export BUILD_HOSTPOT=true export BUILD_JDK=true #要编译的版本 export SKIP_DEBUG_BUILD=true export SKIP_FASTDEBUG_BUILD=true export DEBUG_NAME=debug #把它设置为FALSE可以避免javaws和浏览器Java插件之类的部分build BUILD_DEPLOY=false #把它设置为false就不会build出安装包。因为安装包里有一些奇怪的依赖 #但即便不build出它也已经得到完整的JDK镜像,所以还是不用build它 BUILD_INSTALL=false #存放编译结果 export ALT_OUTPUTDIR=/home/leon/openjdk/build #这两个环境变量必须去掉,不然会有很的事情发生(Makefile脚本检查到有这2个变量变会提示警告) unset CLASSPATH unset JAVA_HOME # make默认目标,将标准错误输出(2:STDERR)与标准输出(1:STDOUT)合并,合并结果作为标准输入通过管道命令传递给tee命令, # tee命令读取标准输入并传递给文件$ALT_OUTPUTDIR/build.log # 参数DEBUG_BINARIES=true用于解决高版本gcc不支持stabs, # 不加可能会报错:cc1plus: error: the "stabs" debug format cannot be used with pre-compiled headers [-Werror=deprecated] make DEBUG_BINARIES=true 2>&1 | tee $ALT_OUTPUTDIR/build.log
全部设置结束之后,可以输入make sanity来检查我们前面所做的设置是否全部正确,
make sanity
如果看到“Sanity check passed.”输出,说明检查通过了。
然后执行build.sh脚本(脚本中最后一行是make命令)进行编译。
$ chmod 755 build.sh $ ./build.sh
5. 编译
执行build.sh脚本(脚本中最后一行是make命令)进行编译。$ chmod 755 build.sh $ ./build.sh
5.1. 我的机器上make后出现的错误及解决方法:
5.1.1. ERROR: echo “* This OS is not supported:” ‘uname -a’; exit 1;注释掉hotspot/make/linux/Makefile里面的checkOS
check_os_version: #ifeq ($(DISABLE_HOTSPOT_OS_VERSION_CHECK)$(EMPTY_IF_NOT_SUPPORTED),) # $(QUIETLY) >&2 echo "*** This OS is not supported:" `uname -a`; exit 1; #endif
或者在make时后面添加参数:DISABLE_HOTSPOT_OS_VERSION_CHECK=OK。(没试过,我采用的是上面方法)
make DISABLE_HOTSPOT_OS_VERSION_CHECK=OK
5.1.2. ERROR: libjvm.so: undefined reference to `void G1SATBCardTableModRefBS::write_ref_array_pre_work
template <class T> void write_ref_array_pre_work(T* dst, int count); /* virtual void write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) { if (!dest_uninitialized) { write_ref_array_pre_work(dst, count); } } virtual void write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized) { if (!dest_uninitialized) { write_ref_array_pre_work(dst, count); } } */
5.2. 编译结束后,将输出类似下面所示内容:
######################################################################## ##### Leaving jdk for target(s) sanity all docs images ##### ######################################################################## ##### Build time 00:02:31 jdk for target(s) sanity all docs images ##### ######################################################################## #-- Build times ---------- Target debug_build Start 2017-06-10 00:35:21 End 2017-06-10 00:38:38 00:00:23 corba 00:00:10 hotspot 00:00:04 jaxp 00:00:06 jaxws 00:02:31 jdk 00:00:03 langtools 00:03:17 TOTAL -------------------------
编译完成后,生成的二进制文件和相关的文件在ALTOUTPUTDIR/j2sdk−image目录下,如果没有定义ALT_OUTPUTDIR环境变量,则默认输出路径为./build/platform/j2sdk-image,其中platform与linux系统有关,可能值是下面之一:
- solaris-sparc
- solaris-sparcv9
- solaris-i586
- solaris-amd64
- linux-i586
- linux-amd64
- windows-i586
- windows-amd64
进入$ALT_OUTPUTDIR/j2sdk-image目录,这是整个JDK的完整编译结果,复制到JAVA_HOME目录,就可以作为一个完整的JDK使用了。
5.3. 查看编译的虚拟机信息
在bin目录下执行./java -version 查看编译的虚拟机信息。
$ ./java -version #输出: openjdk version "1.7.0-internal-debug" OpenJDK Runtime Environment (build 1.7.0-internal-debug-leon_2017_06_09_20_15-b00) OpenJDK 64-Bit Server VM (build 24.80-b07-jvmg, mixed mode)
见以上输出,表示编译成功!
6. 单独编译HotSpot
6.1 只执行hotspot/make目录下的Makefile即可
为了使用build.sh中的变量,只要将hotspot/make下的Makefile复制到build.sh所在目录即可。然后进行编译。这时候虚拟机的输出结果存放在build/hotspot/outputdir/linux_amd64_compiler2目录(不同机器上,最后一个目录名称会有所差别,bsd表示Mac OS系统,内核为FreeBSD,linux表示linux系统,amd64表示是64位JDK,32位是x86,compiler2表示是Server VM,compiler1表示是 Client VM。),进入后可以见到以下几个目录。$ cd build/hotspot/outputdir/linux_amd64_compiler2 $ ls -all total 56 drwxrwxr-x 9 leon leon 4096 Jun 27 17:59 . drwxrwxr-x 4 leon leon 4096 Jun 27 18:11 .. drwxrwxr-x 2 leon leon 4096 Jun 27 17:59 debug drwxrwxr-x 2 leon leon 4096 Jun 27 17:59 fastdebug drwxrwxr-x 7 leon leon 4096 Jun 27 18:00 generated drwxrwxr-x 3 leon leon 20480 Jul 29 18:01 jvmg drwxrwxr-x 2 leon leon 4096 Jun 27 17:59 optimized drwxrwxr-x 2 leon leon 4096 Jun 27 17:59 product drwxrwxr-x 2 leon leon 4096 Jun 27 17:59 profiled -rw-rw-r-- 1 leon leon 1648 Jun 27 17:59 shared_dirs.lst
6.2 编译时出现的错
参考: http://blog.csdn.net/beswkwangbo/article/details/38757677编译时会有几个错
第一个是 fatal error: sys/cdefs.h: No such file or directory。与gcc版本有关,解决办法:sudo apt-get install libc6-dev-i386
第二个是 bits/c++config.h: No such file or directory。解决办法:sudo apt-get install gcc-multilib g++-multilib
第三个是cc1plus: error: the “stabs” debug format cannot be used with pre-compiled headers [-Werror=deprecated],因为高版本的gcc不再支持stabs,解决办法:在make命令中加上 DEBUG_BINARIES=true
第四个是,cc1plus all warnings being treated as errors ubuntu。解决办法:在hotspot/make/makefiles/gcc.make 中,把 -Werror 选项去掉。
最后一个问题是,自举jdk不能是64位的,装个32位的即可。
6.3 运行虚拟机
在编辑结束之后、运行虚拟机之前,还要手工编辑jvmg目录下的env.sh文件,这个文件由编译脚本自动生成,用于设置虚拟机的环境变量,里面已经发布了“JAVA_HOME、 CLASSPATH、 HOTSPOT_BUILD_USER”3个环境变量(需要修改JAVA_HOME变量为当前编译java),还需要增加一个“LD_LIBRARY_PATH”变量,最后env.sh文件内容如下:# Generated by /home/leon/OpenJDK7/jdk7u-dev/hotspot/make/linux/makefiles/buildtree.make : ${JAVA_HOME:=/home/leon/OpenJDK7/build/j2sdk-image} CLASSPATH=.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/jre/lib/i18n.jar HOTSPOT_BUILD_USER="leon in hotspot" LD_LIBRARY_PATH=.:${JAVA_HOME}/jre/lib/amd64/native_threads:${JAVA_HOME}/jre/lib/amd64: export JAVA_HOME CLASSPATH HOTSPOT_BUILD_USER LD_LIBRARY_PATH bash
然后执行以下命令启动虚拟机(这时的启动器名为gamma),输出版本号。
$ cd jvmg $ ./env.sh $ ./gamma -version
输出如下(同build/j2sdk-image/bin/java -version输出一样)
Using java runtime at: /home/leon/OpenJDK7/build/j2sdk-image/jre openjdk version "1.7.0-internal-debug" OpenJDK Runtime Environment (build 1.7.0-internal-debug-leon_2017_06_27_17_51-b00) OpenJDK 64-Bit Server VM (build 24.80-b07-jvmg, mixed mode)
7. 在Eclipse中调试Hotspot虚拟机源码
请参看 Linux下在Eclipse中调试Hotspot虚拟机源码 http://blog.csdn.net/leonliu06/article/details/78495202。参考:
《深入理解Java虚拟机——JVM高级特性与最佳实践》
相关文章推荐
- CentOS上编译OpenJDK8源码 以及 在eclipse上调试HotSpot虚拟机源码
- Linux下在Eclipse中调试Hotspot虚拟机源码
- ubuntu下编译openjdk 并在eclipse调试hotspot
- 在eclipse中调试launcher模块以及已编译launcher源码两份
- 如何利用eclipse编译调试linux源码--以gnome-system-monitor 为例
- 最新ffmpeg编译和用eclipse进行源码调试(linux)
- Linux下用Eclipse编译、安装、运行、调试PostgreSQL源码
- 将Android源码导入eclipse中的方法以及编译Android源码指定模块
- Eclipse3.6与m2eclipse,run-jetty-run插件对WEB项目进行热部署以及在jar源码中进行调试(三)
- 程序开发工具(Java反编译及Linux等)与调试技巧(eclipse,linux)部分数据库插件
- linux下GCC编译环境中二叉树遍历、C语言实现以及调试过程中段错误
- JDK源码重新编译——支持eclipse调试JDK源码--转载
- Eclipse3.6与m2eclipse,run-jetty-run插件对WEB项目进行热部署以及在jar源码中进行调试(三)
- Linux下搭建Eclipse下Hadoop的开发环境以及远程调试
- ubuntu编译并调试OpenJDK8源码实践
- Linux下C程序的编辑,编译和运行以及调试
- Linux下C程序的编辑,编译和运行以及调试