Java/JVM是如何构建的?看看OpenJDK吧!

简介&历史

正如有些人已经知道的那样,从Java7开始,OpenJDK就是Java的参考实现(Reference Implementation)。下图的时间线可以让你了解一下OpenJDK的历史。

bc70d51dc8ffa360f32185cfe67dbd03

OpenJDK历史(2006至今)

看看OpenJDK更详细的过去现在和将来[1]。

如果你想了解从Oracle,Red Hat,etcetera等供应商那里下载得来的JDK或JRE库,那么可以告诉你,它们都是起源于OpenJDK。每个供应商在此基础上添加额外的部件。出于安全,专利或其他的考虑,这些额外的添加部分并不公开源码。

OpenJDK由什么组成?

OpenJDK由许多软件库组成,主要有corba,hotspot,jaxp,jaxws,jdk,langtools,以及nashorn。在OpenJDK8和OpenJDK9之间没有新的软件库加入,但有很多改变和结构调整,主要是因为Jigsaw——Java自身的模块化[2][3][4][5]。

34ac4545b3f17bd20b571092d2845cc1

代码的组成以及语言的分解构成(比例是估计的)

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]:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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影像,总结起来就是下面的几个命令:

(启动过程被简化了,忽略了一些命令,访问上述链接可以得到准确的操作步骤)

1 $ hg clone http://hg.openjdk.java.net/jdk8/jdk8 jdk8 (a)...OpenJDK8

或者

1
2
3
4
$ 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及其隶属项目由以下组织支持发展:JCPOpenjdk 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 - fzr
译文链接: http://www.importnew.com/14610.html
[ 转载请保留原文出处、译者和译文链接。]


如果给你带来帮助,欢迎微信或支付宝扫一扫,赞一下。