java只所以被推广,实际上很大原因是因为本身是跨平台的,很大作用是因为虚拟机的关系。
一般情况下开发人员不需要关注虚拟机内部实现就可以日常开发了,但是有时候涉及到性能的时候就需要了解虚拟机的实现机制了。
那么今天写的内容更多的是关于编译一套自己的虚拟机,为日后了解虚拟机底层原理铺铺路。
编译虚拟机可能会遇到很多坑,也很花费时间。也因大家的环境的差异,可能遇到的问题都不一致。
我只能说把自己遇到的问题都列出来,权当抛砖引玉了。
1首先我们应该下载openjdk的源码,这个openjdk实际上是有一个版本历史的,大家可以去了解一下,
然后这里面的源码内容和oracle jdk内容大部分都是一致的,少数内容不一样。
我这里下载的openjdk 源码是openjdk-7u75-src-b13-18_dec_2014.zip,每个人的版本可能不太一样,不过 是openjdk的源码就行。
2除了上面的东西要准备,其实还要准备一个oracle的jdk,这个jdk我用的是jdk-6u32-linux-x64.bin。
3然后是在linux上先准备好各种依赖,这些依赖获得方式待会儿会讲,另外要讲的是,我这里的linux系统
是ubuntu的 16.04LTS 64位的,所以之前的东西也最好都准备64位的。
东西都准备好了,现在我们开干!!!!
1如果之前你设置了java_home或者classpath环境变量,请先注释掉。
2将openjdk-7u75-src-b13-18_dec_2014.zip解压后得到openjdk文件夹,我们把他放到/usr下。
3执行jdk-6u32-linux-x64.bin,得到jdk1.6.0_32文件夹,我们讲这个文件夹放到/usr/java下。
4输入vim /etc/profile,在最后加入如下内容:
export LANG=C #BootStrap-JDK的安装路径,替换为自己bootstrap-JDK的路径 export ALT_BOOTDIR=/usr/java/jdk1.6.0_32 #同上,我之前使用的是openjdk编译的,后面运行hotspot时出现问题替换为oracleJDK,读者可以直接替换为OracleJDK export ALT_JDK_IMPORT_PATH=/usr/java/jdk1.6.0_32 #规定几个线程来执行这个脚本 export HOTSPOT_BUILD_JOBS=4 export ALT_PARALLEL_COMPILE_JOBS=4 #要编译的内容,读者可以根据需要自行选择 export BUILD_LANGTOOLS=true #export BUILD_JAXWS=false #export BUILD_JAXP=false #export BUILD_CORBA=false export BUILD_HOTSPOT=true export BUILD_JDK=true export SKIP_COMPARE_IMAGES=true BUILD_DEPLOY=false BUILD_INSTALL=false #编译结果存放的路径,建议存放在openjdk源码中build文件夹 export ALT_OUTPUTDIR=/usr/openjdk/build export ALLOW_DOWNLOADS=true #这两个环境变量需要去掉,不然会出问题 unset JAVA_HOME unset CLASSPATH make 2>&1 | tee $ALT_OUTPUTDIR/build.log
注意的是需要source /etc/profile,以更新配置。但是输入后会马上跑起来,但是现在是不会成功的,因为依赖那些还没弄好。直接马上接着按ctrl+c以暂停。
5在终端执行一些命令以安装必要的依赖,命令如下:
sudo apt-get install build-essential gawk m4 libasound2-dev libcups2-dev libxrender-dev xorg-dev xutils-dev x11proto-print-dev binutils libmotif-common ant
有些地方还安装了openjdk-6-jdk,其实这里不安装这个更好,我们用的是oracle的jdk来编译我们的openjdk源码,不建议用openjdk-6-jdk来编译openjdk源码,那也正是我build.sh脚本里面指向的jdk地址是export ALT_BOOTDIR=/usr/java/jdk1.6.0_32的原因。
6现在我们到/usr/openjdk目录去执行make sanity命令,检查是否配置都没问题了。如果没有问题就会显示
7万事具备,只欠东风,输入make,开始编译,编译出的东西会生成在/usr/openjdk/build目录。
流程就是这样的,不过期间会出现一些问题,根据他报的错我们要修正一些错误,修正之后再继续make命令接着编译。
下面是我遇到的一些错误和解决办法。
1>
echo "*** This OS is not supported:" `uname -a`; exit 1;
openjdk/hotspot/make/linux/Makefile:240: recipe for target 'check_os_version' failed
解决:
将/openjdk/hotspot/make/linux/Makefile中的check_os_version下面三行注释掉
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
2>
undefined reference to `void G1SATBCardTableModRefBS::write_ref_array_pre_work
解决:将hotspot/src/share/vm/gc_implementation/g1里的g1SATBCardTableModRefBS.cpp
template <class T> void G1SATBCardTableModRefBS::write_ref_array_pre_work(T* dst, int count) { if (!JavaThread::satb_mark_queue_set().is_active()) return; T* elem_ptr = dst; for (int i = 0; i < count; i++, elem_ptr++) { T heap_oop = oopDesc::load_heap_oop(elem_ptr); if (!oopDesc::is_null(heap_oop)) { enqueue(oopDesc::decode_heap_oop_not_null(heap_oop)); } } }内容下加上如下
//2017-10-19 Vicent_Chen added void G1SATBCardTableModRefBS::write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) { if (!dest_uninitialized) { write_ref_array_pre_work(dst, count); } } void G1SATBCardTableModRefBS::write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized) { if (!dest_uninitialized) { write_ref_array_pre_work(dst, count); } } //2017-10-19 Vicent_Chen added
将hotspot/src/share/vm/gc_implementation/g1里的g1SATBCardTableModRefBS.hpp如下部分
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); } }
注释掉,然后在加入virtual void write_ref_array_pre(oop* dst, int count, bool dest_uninitialized); virtual void write_ref_array_pre(narrowOop* dst, int count, bool dest_unintialized);
3>
Error: time is more than 10 years from present: 1136059200000
解决:
openjdk/jdk/src/share/classes/java/util/CurrencyData.properties文件中以下时间改成10年以内
AZ=AZM;2005-12-31-20-00-00;AZN
MZ=MZM;2006-06-30-22-00-00;MZN
RO=ROL;2005-06-30-21-00-00;RON
TR=TRL;2004-12-31-22-00-00;TRY
VE=VEB;2008-01-01-04-00-00;VEF
4>之后可能在编译RMIServerImpl_Stub.class的时候,很可能是内存不够了,因为我通过系统监视器观察得到这段时间内内存在暴增,具体原因也不知道,但是我连续几次在make命令重新来的时候,到最后一次
又成功了。所以遇到这种情况这种情况可以多次重来。最后一次内存就没有暴增了。
编译成功就是如下的样子了:
之后在build文件夹内就能找到你编译好的jdk。
谢谢大家,有什么不明了的可以向我提问。
忍者必须死34399账号登录版 最新版v1.0.138v2.0.72
下载勇者秘境oppo版 安卓版v1.0.5
下载忍者必须死3一加版 最新版v1.0.138v2.0.72
下载绝世仙王官方正版 最新安卓版v1.0.49
下载Goat Simulator 3手机版 安卓版v1.0.8.2
Goat Simulator 3手机版是一个非常有趣的模拟游
Goat Simulator 3国际服 安卓版v1.0.8.2
Goat Simulator 3国际版是一个非常有趣的山羊模
烟花燃放模拟器中文版 2025最新版v1.0
烟花燃放模拟器是款仿真的烟花绽放模拟器类型单机小游戏,全方位
我的世界动漫世界 手机版v友y整合
我的世界动漫世界模组整合包是一款加入了动漫元素的素材整合包,
我的世界贝爷生存整合包 最新版v隔壁老王
我的世界MITE贝爷生存整合包是一款根据原版MC制作的魔改整