Java/JVM是如何构建的?看看OpenJDK吧!
简介&历史
正如有些人已经知道的那样,从Java7开始,OpenJDK就是Java的参考实现(Reference Implementation)。下图的时间线可以让你了解一下OpenJDK的历史。
如果你想了解从Oracle,Red Hat,etcetera等供应商那里下载得来的JDK或JRE库,那么可以告诉你,它们都是起源于OpenJDK。每个供应商在此基础上添加额外的部件。出于安全,专利或其他的考虑,这些额外的添加部分并不公开源码。
OpenJDK由什么组成?
OpenJDK由许多软件库组成,主要有corba,hotspot,jaxp,jaxws,jdk,langtools,以及nashorn。在OpenJDK8和OpenJDK9之间没有新的软件库加入,但有很多改变和结构调整,主要是因为Jigsaw——Java自身的模块化[2][3][4][5]。
Java语言和平台是如何构建的?
Java通过引导一个旧版本的Java——例如,Java以其自身为构件建立。旧的组件被组合在一起创建一个新的组件,即成为下一阶段的结构单元。关于这种自展的一个很好的例子请参考 Scheme from Scratch或是 Wikipedia [7]。
OpenJDK8使用JDK7编译和构建,类似地,OpenJDK9 则使用JDK8编译构建。理论上,OpenJDK8是可以使用从其自身创建的影像编译的,同理,OpenJDK9也能用OpenJDK9编译。使用一个叫做循环启动影像的进程——创建OpenJDK的JDK影像,使用同样的影像,OpenJDK再一次被编译。也可以用make命令实现OpenJDK的编译:
$ make bootcycle-images # Build images twice, second time with newly built JDK
make命令在OpenJDK8和OpenJDK9下都提供了很多设置选项,可以通过命名的方式建立独立的组件或模块。如下:
$ make [component-name] | [module-name]
甚至并行运行多个构建过程,如下:
$ make JOBS= # Run parallel make jobs
最后,用install选项安装上述已构建的组件,如下:
$ make install
一些被神话了的东西
具体来说,OpenJDK或是Hotspot都不完全是用C或C++写的,代码库中相当一部分代码是良好的OLE(对象连接与嵌入)Java(详细请看上文的组成图表)。所以对OpenJDK作出贡献并不要求你必须是核心硬件开发者。即使是底层的C/C++代码库也不是那么让人望而生畏。下面就是从HotSpot repo的vm/memory/universe.cpp中摘录出的一个代码片段——http://hg.openjdk.java.net/jdk6/jdk6/hotspot/raw-file/a541ca8fa0e3/src/share/vm/memory/universe.cpp [10]:
Universe::initialize_heap() if (UseParallelGC) { #ifndef SERIALGC Universe::_collectedHeap = new ParallelScavengeHeap(); #else // SERIALGC fatal("UseParallelGC not supported in this VM."); #endif // SERIALGC } else if (UseG1GC) { #ifndef SERIALGC G1CollectorPolicy* g1p = new G1CollectorPolicy(); G1CollectedHeap* g1h = new G1CollectedHeap(g1p); Universe::_collectedHeap = g1h; #else // SERIALGC fatal("UseG1GC not supported in java kernel vm."); #endif // SERIALGC } else { GenCollectorPolicy* gc_policy; if (UseSerialGC) { gc_policy = new MarkSweepPolicy(); } else if (UseConcMarkSweepGC) { #ifndef SERIALGC if (UseAdaptiveSizePolicy) { gc_policy = new ASConcurrentMarkSweepPolicy(); } else { gc_policy = new ConcurrentMarkSweepPolicy(); } #else // SERIALGC fatal("UseConcMarkSweepGC not supported in this VM."); #endif // SERIALGC } else { // default old generation gc_policy = new MarkSweepPolicy(); } Universe::_collectedHeap = new GenCollectedHeap(gc_policy);
(请注意上述代码片段可能已在发布在本文后的时间里有所变更了)
从上面的代码块中可以明显看出的是,我们的目的在于展示如何使用预编译符号创建HotSpot代码来支持某种类型的GC(GenCollector),比如Serial GC(串行GC)或者Parallel GC(并行GC)。在上述代码块中,在一种或多种GC转换器被触发之前就已经选择确定了GC策略的类型了,比如,当UseAdaptiveSizePolicy被激活后,才可以选择Asynchronous Concurrent Mark and Sweep策略。在Use Serial GC和Use Concurrent Mark Sweep GC二者仅选其一的情况下,被选中的GC策略就是Mark and Sweep策略。除了提供读起来像英文一样流畅的格式简洁的代码之外,又说了这么多,已经相当清楚了,再多说就很啰嗦了。
更多注释可以在Adopt OpenJDK Intermediate & Advance experiences [11] 文件夹的Deep Dive Hotspot stuff部分找到。
构建自己的JDK或JRE的步骤
早些时候我们提到JDK和JRE的影像——这些不再是只给Java世界中的大玩家们提供了,你和我都能很轻易的构建这样的影像。这过程中的步骤已经被简化了,想快速开始请参看 Adopt OpenJDK Getting Started Kit和 Adopt OpenJDK Intermediate & Advance experiences 文件。想要看更详细的版本请参看 Adopt OpenJDK home page。要从OpenJDK代码库中基本构建一个JDK影像,总结起来就是下面的几个命令:
(启动过程被简化了,忽略了一些命令,访问上述链接可以得到准确的操作步骤)
$ hg clone http://hg.openjdk.java.net/jdk8/jdk8 jdk8 (a)...OpenJDK8
或者
$ hg clone http://hg.openjdk.java.net/jdk9/jdk9 jdk9 (a)...OpenJDK9 $ ./get_sources.sh (b) $ bash configure (c) $ make clean images (d)
(设置的步骤和一些命令省略了,查看上面的链接可以查看更详细的步骤)
解释一下上述每个步骤的工作:
就像使用克隆版本库一样复制OpenJDK每次修改的版本。。。
一旦(a)已经完成,进入新创建的文件夹,执行get_sources.sh命令,等价于一次git fetch命令(抓取)或一次git pull命令(拉取远程仓库)。因为步骤(a)中只是降低基础文件而不是所有文件的成本。
这里运行一个脚本检查并创建编译与构建过程所需的配置
步骤(c)完成后,我们就算是从构建好的模块中完成了一个JDK和JRE影像文件的编译,构建和创建。
正如你看到的这样,这些步骤易如反掌,照做就可以建立一个自定义工具或者JDK/JRE影像[步骤a只需要执行一次]。
好处
• 促进Java语言&平台的发展和改进
• 了解Java语言和平台的内部构件
• 在达到以上两点的同时了解OS平台和其他技术
• 参与到F/OSS项目中
• 保持立于Java/JVM范畴的最新动态之上
• 提供有助于专业且还不能从其他如书籍,训练,工作实习,大学课程等来源获得的知识和经验
• 事业提升
• 个人发展(软技能及网络)
贡献
加入项目Adopt OpenJDK和 Betterrev,向我们提供这些项目中任何与java有关的反馈。可以从加入Adoption Discuss邮件列表和其他OpenJDK相关的邮件列表开始,这些可以让你了解OpenJDK相关的最新进展和变化。为你看到的任何项目建立分支库(通过github中的fork repo),然后提交自己的改变(通过github中发起一个Pull Request)。
感谢与支持
Adopt OpenJDK及其隶属项目由以下组织支持发展:JCP(Openjdk team),JUGs如London Java Community,SouJava和巴西其他的JUGs,欧洲许多的JUGs比如BGJUG (Bulgarian JUG) [18], BeJUG (Belgium JUG)[19],Macedonian JUG [20],还有许多其他的比较小的JUGs。我们希望未来会有更多JUGs组织和个人参与进来。如果你或你的JUG希望参与请联系我们。
原文链接: javacodegeeks 翻译: ImportNew.com - 范 忠瑞
译文链接: http://www.importnew.com/14610.html