做 Java 开发的你,有编译过自己的 JDK 玩玩儿吗
我是风筝,公众号「古时的风筝」,一个不只有技术的技术公众号,一个在程序圈混迹多年,主业 Java,另外 Python、React 也玩儿的 6 的斜杠开发者。 Spring Cloud 系列文章已经完成,可以到 我的github 上查看系列完整内容。也可以在公众号内回复「pdf」获取我精心制作的 pdf 版完整教程。
你每天写的 Java 代码都需要 JDK 的支持,都要跑在 JVM 上,难道你就不好奇 JDK 长什么样子吗。好奇,就来编译并实现一个自己的 JDK 吧。
本次编译环境 macOS 10.12,编译的是 JDK 11 版本。
安装 OpenJDK 11
编译 OpenJDK 需要先在机器上安装 OpenJDK 10 或者 OpenJDK 11,作为 Boot JDK。 先安装 openJDK 11 编译需要,可以到 adoptopenjdk 网站去下载。
pkg 格式安装
进入页面 https://adoptopenjdk.net/index.html?variant=openjdk11&jvmVariant=hotspot
直接下载下载,然后双击就可以完成安装了。
tar.gz 格式安装
1、进入页面 https://adoptopenjdk.net/installation.html?variant=openjdk11&jvmVariant=hotspot#x64_mac-jdk
下载 tar.gz 包
2、解压
tar -xf OpenJDK11U-jdk_x64_mac_hotspot_11.0.5_10.tar.gz
解压后是一个 macOS 包,可通过右键->显示包内容查看里面的文件。
3、加入环境变量 PATH 中,当然如果你使用其他版本的 JDK 作为开发使用,请忽略这一步。
export PATH=$PWD/jdk-11.0.5+10/Contents/Home/bin:$PATH
4、macOS JDK 默认目录在/Library/Java/JavaVirtualMachines
,把第 2 步解压的内容放到此目录下,之后编译的过程中会在这个目录下查找 JDK 10 或 JDK 11。
下面是我本地的目录结构,有 7 、8、11 这三个版本,开发时候还是默认使用 8 的。
安装 xcode
实际上我们需要的不是 xcode,而是 LLVM 的编译命令 clang。当然你可以单独安装 LLVM,但限于此篇是写给 Java 开发者的,安装 xcode 是最简单的版本。
我本地是很早之前安装的 xcode 8.1,编译起来是没问题的,如果你用的是比较新的版本,应该也不会出现什么问题,可以亲自试一试。
开始编译
1、下载 OpenJDK 11 源码
OpenJDK 的源码放在了网站 http://hg.openjdk.java.net/ 上,我们要下载的 JDK11 目录在 http://hg.openjdk.java.net/jdk-updates/jdk11u/。
进入页面后,先点击左侧的 browse,再选择一种压缩格式下载。
当然还可以用 hg 命令 clone 到本地,使用 hg 需要安装 mercurial,如果网速不好或者不稳定,建议不要使用这种方式。
hg clone https://hg.openjdk.java.net/jdk/jdk11/
2、解压源码包
将你刚刚下载的压缩包解压,请解压到一个全英文目录下,不要使用中文,减少编译时带来的麻烦。
3、configure
进入上一步解压后的目录,执行如下命令。
sh configure --with-target-bits=64 --enable-ccache --with-jvm-variants=server --with-boot-jdk-jvmargs="-Xlint:deprecation -Xlint:unchecked" --disable-warnings-as-errors --with-debug-level=slowdebug 2>&1 | tee configure_mac_x64.log
执行这个命令的前提是我已经将 OpenJDK 11 放到了 /Library/Java/JavaVirtualMachines
目录下。
如果不放到这个目录下,也是可以的,需要额外指定参数
--with-boot-jdk=OpenJDK 目录
如果出现如下输出,说明这一步就正常了。
4、make
正式开始编译了,使用 make 命令即可。
make
首次编译会比较慢,我的是 MacBook Pro i5 8G 的那款,大概编译了 10 几分钟吧。当出现如下输出的时候,说明编译成功。
Finished building target 'default (exploded-image)' in configuration 'macosx-x86_64-normal-server-slowdebug'
编译好之后,会在当前目录出现 build 目录,进去之后,看到有个 macosx-x86_64-normal-server-slowdebug
就是最终的目录。
IDEA 中配置使用编译好的 JDK
1、打开 IDEA ,找到 File->Project Structure。
2、添加一个 JDK
3、选择上面源码编译好的 jdk
4、最后启动项目的时候指定这个 JDK 就可以了。
用 CLion 调试
1、打开 CLion ,导入项目,选择下载的源码所在位置的 src 目录。
2、配置 Debug Configurations,选择 Executable 为编译好的 java 可执行程序,在 bin 目录下,并且移除 Build 设置。
Program arguments 设置为 -version,也可以设置其他的。设置为 -version 的意思是 java -version。
3、最后在源码中打个断点,比如 jni.cpp 或 thread.cpp 中,然后点击 debug ,就可以调试啦。
打造自己的 JDK
标题说的有点儿悬,打造自己的 JDK 哪儿有那么容易,况且还确实没那个实力。这里就是介绍一种思路,比如有些时候,我们调试 Java 代码最后发现走到了 JVM 层,这种情况下,我们就跟不进去了。执行到 JVM 层之后,里面的各种变量是怎么变换的我们就不知道了。这时候,我们找到 JVM 对应的代码稍微改一下,比如加个 printf 输出一下参数值就可以清晰的看出来了。
修改 JDK 代码
我在打开的 CLion 中找到了 java.c 文件的 JavaMain(void * _args)
方法,在里面加了一行打印代码,就勉强算实现了自己的 JDK 吧(微笑脸)。
万里长征第一步嘛,别的不重要,留下脚印儿才是关键。
printf("古时的风筝 JDK \n");
重新编译修改后的源码
修改之后,在终端中进入到源码目录的根目录,然后执行 make 命令。
因为之前已经编译过了,所以再次执行 make 是进行的增量编译,所以速度很快。
好了,见证奇迹的时刻到了
我们之前已经在 IDEA 中添加了编译好的 JDK,并且指定给了一个项目。仅为测试,代码如下。
public static void main(String[] args){ System.out.println("hello jvm"); }
当我们运行这个项目的时候,如果是平常的 JDK,会在控制台输出 hello jvm ,对不对。
可是,现在指定的不是平常的 JDK ,是被我加持过的 JDK 。
开始运行,输出的结果如下,看到没,刚刚加上的那行代码起作用了。
风筝说
真正能做到 JDK 定制开发的人并不多,我也完全没这个实力。但是每个 Java 开发者都编译一下 JDK 源码,翻一翻代码还是很有必要的。毕竟,我们每天写的代码都需要 JDK 的支持,都要跑在 JVM 上,我们就不好奇它们长成什么模样吗。
另外,这也可能为我们日常解决问题提供一种思路。有人说,最好的老师就是搜索引擎,大多数情况下是没错,但有的时候最好的方式往往就是看一眼源码。
为什么有的人解决问题的速度快,有些看似不能解决的问题放到大牛手里就能很快解决。有时候就是解决问题的维度不一样,人家是在三维的世界里,你却一直在二维的平面里转圈圈,比方说遇到程序问题,只能分析 Java 层面的问题这就是二维,进到 JDK、JVM 源码那就是进到的三维。维度高了,角度变了,解决问题的可能性和方式也就多了。这就好比三体里高等文明利用二向箔进行打击,完全不在一个体量下。
赶紧行动吧,编译一个你自己的 JDK。
我是风筝,公众号「古时的风筝」,一个在程序圈混迹多年,主业 Java,另外 Python、React 也玩儿的很 6 的斜杠开发者。可以在公众号中加我好友,进群里小伙伴交流学习,好多大厂的同学也在群内呦。
技术交流还可以加群或者直接加我微信。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
一文讲透Cluster API的前世、今生与未来
Cluster API是一个Kubernetes项目,它将声明式Kubernetes风格的API用于集群的创建、配置和管理。它通过使用时CustomResourceDefinitions(CRDs)来扩展被Kubernetes API Server暴露的API来实现这些功能,从而允许用户创建新资源,例如集群(指Kubernetes集群)和Machine(指组成集群的节点的Machine)。然后每个资源的控制器负责对这些资源的更改做出反应,以启动集群。API的设计可以让不同的基础架构提供程序可以与其集成,进而提供针对其环境的特定逻辑。 Cluster API项目仍处于早期阶段,但是当前的情况已经证明了它能带来强大的功能。这篇文章的目的是总结迄今为止该项目的功能,并展望后续版本的功能。 过去、现在和未来 撰写这篇文章的时候,Cluster API最新发布的版本实现了v1alpha2。在这里,我们将讨论该API的转换以及提供程序如何与之集成。 过去:v1alpha1 最初,Cluster API的v1alpha1实现要求提供程序需要在其项目中包含Cluster API控制器代码,并实现act...
- 下一篇
Spring AOP 源码解析:注解式切面增强机制
IoC 和 AOP 被称为 Spring 两大基础模块,支撑着上层扩展的实现和运行。虽然 AOP 同样建立在 IoC 的实现基础之上,但是作为对 OOP(Object-Oriented Programing) 的补充,AOP(Aspect-Oriented Programming) 在程序设计领域拥有其不可替代的适用场景和地位。Spring AOP 作为 AOP 思想的实现,被誉为 Spring 框架的基础模块也算是实至名归。Spring 在 1.0 版本的时候就引入了对 AOP 的支持,并且随着版本的迭代逐渐提供了基于 XML 配置、注解,以及 schema 配置的使用方式,考虑到实际开发中使用注解配置的方式相对较多,所以本文主要分析注解式 AOP 的实现和运行机制。 注解式 AOP 示例 首先我们还是通过一个简单的示例演示一下注解式 AOP 的具体使用。假设我们声明了一个 IService 接口,并提供了相应的实现类 ServiceImpl,如下: public interface IService { void sayHello(); void sayHelloTo(String...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Red5直播服务器,属于Java语言的直播服务器
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS8编译安装MySQL8.0.19
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS6,CentOS7官方镜像安装Oracle11G
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8安装Docker,最新的服务器搭配容器使用