本文不讲解编译openjdk8的过程,而是专注于用最少的步骤把openjdk8源码编译构建成jdk。
-
进行本文的实践有个前提:请读者们先在电脑上安装docker
-
总的来说整个过程只有六步,如下:
- 指定镜像创建一个容器,这个镜像中已经把编译所需的工具和源码都准备好了;
- 进入容器;
- 找到openjdk8源码位置,有兴趣的读者此时可以修改源码;
- 在指定目录开始configure;
- configure完成后开始编译;
- 编译成功,进入build目录,检查验证全新的jdk;
- 接下来开始实战吧:
指定镜像创建容器
- 在控制台执行命令:
docker run --name=compilejdk -idt bolingcavalry/bolingcavalryopenjdk:0.0.1
- 这个命令会先去网站下载镜像bolingcavalry/bolingcavalryopenjdk:0.0.1,然后创建一个名字叫compilejdk的容器;
进入容器
- 执行以下命令即可进入容器:
docker exec -it compilejdk /bin/bash
找到openjdk8源码位置,修改jdk源码
- 和本次编译相关的资源都放在**/usr/local/openjdk**下面了,如下图:
- 我们这次要修改的文件是/usr/local/openjdk/hotspot/src/share/vm/runtime/objectMonitor.cpp;
- 执行命令vi /usr/local/openjdk/hotspot/src/share/vm/runtime/objectMonitor.cpp编辑这个文件;
- 找到方法**ObjectMonitor::exit(bool not_suspended, TRAPS)**;
- 再找到该方法里面的**int QMode = Knob_QMode ;**这行代码;
- 在下面新增一行代码printf("**-QMode : %d", QMode);,也就是将QMode的值在控制台打印出来,如下图:
-
修改完毕后保存退出vi;
-
新增这行代码的作用,是在每个synchronize{}代码块结束的时候,也就是线程释放锁的时候,在控制台将QMode这个参数的值打印出来;
在指定目录开始configure
- 回到目录**/usr/local/openjdk**,执行以下命令进行configure:
./configure --with-debug-level=slowdebug
- 执行完毕的效果如下图所示:
开始编译
- 回到目录**/usr/local/openjdk**,执行以下命令开始编译:
make all ZIP_DEBUGINFO_FILES=0 DISABLE_HOTSPOT_OS_VERSION_CHECK=OK CONF=linux-x86_64-normal-server-slowdebug
- 编译耗时长短和机器硬件配置有关,我的2014版mac pro13大约用20分钟完成编译,执行完毕的效果如下图所示:
检查和验证全新的jdk
-
进入目录**/usr/local/openjdk/build/linux-x86_64-normal-server-slowdebug**,内容如下:
-
图中的jdk文件夹中就是全新的jdk,进入这个文件夹再进入里面的bin目录,执行**./java -version**命令可以看到如下内容:
-
如上图“1.8.0-internal-debug-_2017_08_30_13_00-b00“表示是最新构建的jdk版本,至于前面那几行“******-QMode : 0“就是系统执行了释放锁的api,导致我们添加的那行代码被执行了;
-
接下来我们写个java类在这个jdk上运行试试,在**/usr/local/openjdk/build/linux-x86_64-normal-server-slowdebug/jdk/bin**目录下,用vi命令创建Test.java文件,内容如下:
public class Test{
public static void main(String[] args){
Object lock = new Object();
new Thread(()->{
synchronized(lock){
System.out.println("1. get lock success");
System.out.println("1. release lock start");
}
System.out.println("1. release lock end");
}).start();
new Thread(()->{
synchronized(lock){
System.out.println("2. get lock success");
System.out.println("2. release lock start");
}
System.out.println("2. release lock end");
}).start();
}
}
-
代码很简单,就是执行了一次持有锁再释放锁的操作;
-
还是在jdk/bin目录下,执行以下命令编译java文件,注意,一定要加上./,否则就不会使用最新的jdk:
./javac Test.java
-
执行完javac命令之后,再执行**./java Test**就能把编译好的Test.class文件运行起来了,效果如下:
-
如上图所示,在释放锁的时候会把我们添加的代码打印出来;
-
以上就是在docker下最快速完成openjdk8编译的过程了,是不是很容易呢?如果您想了解更多细节,例如编译环境需要准备哪些材料,镜像如何制作,甚至如何用GDB给jvm打断点单步调试,请参考下面这两篇文章:
- 《在docker上编译openjdk8》
- 《修改,编译,GDB调试openjdk8源码(docker环境下)》