1.6 实战:自己编译JDK 1.6.4 进行编译
需要下载的编译环境和依赖项目都齐备后,我们就可以按照默认配置来开始编译了,但通常我们 编译OpenJDK的目的都不仅仅是为了得到在自己机器中诞生的编译成品,而是带着调试、定制化等需 求,这样就必须了解OpenJDK提供的编译参数才行,这些参数可以使用“bash configure–help”命令查询 到,笔者对它们中最有用的部分简要说明如下:
--with-debug-level=<level>
:设置编译的级别,可选值为release、fastdebug、slowde-bug,越往后进 行的优化措施就越少,带的调试信息就越多。还有一些虚拟机调试参数必须在特定模式下才可以使 用。默认值为release。--enable-debug
:等效于–with-debug-level=fastdebug。--with-native-debug-symbols=<method>
:确定调试符号信息的编译方式,可选值为none、 internal、external、zipped。--with-version-string=<string>
:设置编译JDK的版本号,譬如java-version的输出就会显示该信息。 这个参数还有–with-version-= 的形式,其中part可以是pre、opt、build、major、minor、 security、patch之一,用于设置版本号的某一个部分。 --with-jvm-variants=<variant>[,<variant>...]
:编译特定模式(Variants)的HotSpot虚拟机,可以 多个模式并存,可选值为server、client、minimal、core、zero、custom。--with-jvm-features=<feature>[,<feature>...]
:针对–with-jvm-variants=custom时的自定义虚拟机特 性列表(Features),可以多个特性并存,由于可选值较多,请参见help命令输出。--with-target-bits=<bits>
:指明要编译32位还是64位的Java虚拟机,在64位机器上也可以通过交叉 编译生成32位的虚拟机。--with-<lib>=<path>
:用于指明依赖包的具体路径,通常使用在安装了多个不同版本的Bootstrap JDK和依赖包的情况。其中lib的可选值包括boot-jd、freetype、cups、x、alsa、libffi、jtreg、libjpeg、 giflib、libpng、lcms、zlib。--with-extra-<flagtype>=<flags>
:用于设定C、C++和Java代码编译时的额外编译器参数,其中 flagtype可选值为cflags、cxxflags、ldflags,分别代表C、C++和Java代码的参数。--with-conf-name=<name>
:指定编译配置名称,OpenJDK支持使用不同的配置进行编译,默认会 根据编译的操作系统、指令集架构、调试级别自动生成一个配置名称,譬如“linux-x86_64-server- release”,如果在这些信息都相同的情况下保存不同的编译参数配置,就需要使用这个参数来自定义配 置名称。
以上是configure命令的部分参数,其他未介绍到的可以使用“bash configure–help”来查看,所有参 数均通过以下形式使用:
1 | bash configure [options] |
譬如,编译FastDebug版、仅含Server模式的HotSpot虚拟机,命令应为:
1 | bash configure --enable-debug --with-jvm-variants=server |
configure命令承担了依赖项检查、参数配置和构建输出目录结构等多项职责,如果编译过程中需 要的工具链或者依赖项有缺失,命令执行后将会得到明确的提示,并且给出该依赖的安装命令,这比 编译旧版OpenJDK时的“make sanity”检查要友好得多,譬如以下例子所示:
1 | configure: error: Could not find fontconfig! You might be able to fix this by running 'sudo apt-get install libfontconfig1-dev'. |
如果一切顺利的话,就会收到配置成功的提示,并且输出调试级别,Java虚拟机的模式、特性, 使用的编译器版本等配置摘要信息,如下所示:
1 | A new configuration has been successfully created in |
在configure命令以及后面的make命令的执行过程中,会在“build/配置名称”目录下产生如下目录结 构。不常使用C/C++的读者要特别注意,如果多次编译,或者目录结构成功产生后又再次修改了配 置,必须先使用“make clean”和“make dist-clean”命令清理目录,才能确保新的配置生效。编译产生的目 录结构以及用途如下所示:
1 | buildtools/:用于生成、存放编译过程中用到的工具 |
依赖检查通过后便可以输入“make images”执行整个OpenJDK编译了,这里“images”是“product- images”编译目标(Target)的简写别名,这个目标的作用是编译出整个JDK镜像,除了“product- images”以外,其他编译目标还有:
1 | hotspot:只编译HotSpot虚拟机 |
笔者使用Oracle VM VirtualBox虚拟机,启动4条编译线程,8GB内存,全量编译整个OpenJDK 12 大概需近15分钟时间,如果之前已经全量编译过,只是修改了少量文件的话,增量编译可以在数十秒 内完成。编译完成之后,进入OpenJDK源码的“build/配置名称/jdk”目录下就可以看到OpenJDK的完整 编译结果了,把它复制到JAVA_HOME目录,就可以作为一个完整的JDK来使用,如果没有人为设置 过JDK开发版本的话,这个JDK的开发版本号里默认会带上编译的机器名,如下所示:
1 | > ./java -version |