作者:大家好,我是 CodeStats。
一个在底层技术上“考古”了四年的硬核爱好者,也是 WWAIC(全周项目AI编程) 范式的提出者和实践者。我曾手写过一个完整的 Java Web 框架(从 IoC 容器到嵌入式 Tomcat,代码全开源),也喜欢用通俗的语言拆解 CPU、JVM、操作系统的运行本质。
我的技术信条:所有高深的技术,最后都能用大白话讲清楚。如果讲不清楚,说明还没真正理解。
本文核心收获:
-
彻底搞清 OpenJDK 和 OracleJDK 的关系、许可证差异及收费真相
-
完整梳理 Java 从 JDK 1.0 到 JDK 21 的 30 年演进脉络
-
掌握 JDK 9 模块化前后目录结构变化,搞懂 jmods 和 lib 的分工
-
理解 JPMS 与 OSGi 的根本差异:为什么一个禁止同名包,一个允许
-
搞清 JDK 9+ 移除独立 JRE 的原因、运行机制及 jlink 用法
-
吃透 JDK 21 虚拟线程的三大原理:M:N 调度、挂载/卸载、Continuation
-
弄清楚 javax 包为什么被移除、移除了什么、由谁维护
-
彻底分清 Java 标准 API 与内部 API 的边界,避免踩坑
目录
OpenJDK 和 OracleJDK 什么关系?为什么开源还被限制?
Java 30年演进:从 JDK 1.0 到虚拟线程
OpenJDK 与 OracleJDK 何时分岔?收费为何还有人选?还有哪些厂商发行版?
高版本 JDK 如何选?LTS 还是非 LTS?OpenJDK 还是厂商发行版?
JDK 9 模块化后目录结构变了什么?jmods 和 lib 各有什么用?
JDK 模块化 vs OSGi:为什么 JPMS 不支持同名包而 OSGi 支持?
JDK 9+ 为什么不带 JRE 了?运行时从哪来?为什么还有独立 JRE 下载?
JDK 21 虚拟线程的本质和原理是什么?
javax 包为什么被移除?哪些功能没了?由谁维护?
Java 标准 API 和内部 API 有什么区别?
一、OpenJDK 和 OracleJDK 什么关系?为什么开源还被限制?
1.1 历史渊源
Java 由 Sun Microsystems 发明。2006 年,Sun 在 JavaOne 大会上宣布 Java 开源,即 OpenJDK——Java SE 的开源参考实现。
2009 年,Oracle 收购 Sun,Java 的维护权易主。
1.2 源码层面:基本是同一个东西
OracleJDK 基于 OpenJDK 源码构建。从 JDK 7 开始,Oracle 员工构建 OracleJDK 时,先从 OpenJDK 代码库签出代码,再合并少量私有部分。两者在功能、性能、执行逻辑上基本一致。
1.3 核心区别:许可证
| 许可证 | GPL v2 | Oracle 商业协议 |
| 商业使用 | ✅ 允许 | ❌ 仅个人研究 |
| 发布形式 | 源码 | 二进制安装包 |
开源 ≠ 无限制使用。OpenJDK 的 GPL v2 允许商业使用,但 OracleJDK 的私有部分(如 Flight Recorder 内部实现)需要付费才能在生产环境使用。
二、Java 30年演进:从 JDK 1.0 到虚拟线程
2.1 萌芽期:JDK 1.0 – 1.1(1995-1997)
1995 年 JDK 1.0 发布,口号 "Write Once, Run Anywhere"。JDK 1.1 引入 JDBC、内部类、反射、RMI。
2.2 企业级时代:J2EE 1.2 – 1.4(1998-2002)
1998 年 Java 2 发布,拆分为 J2SE(标准)、J2EE(企业)、J2ME(微型)。
2.3 黄金十年:JDK 5 – JDK 8(2004-2014)
JDK 5(2005):泛型、枚举、注解、自动装箱、增强 for 循环,奠定 Java 十年技术核心。
JDK 8(2014):里程碑版本——Lambda、Stream API、新日期 API、接口默认方法。至今仍是市场占有率最高的 JDK。
2.4 模块化革命:JDK 9(2017)
Project Jigsaw 落地。在 package 和 jar 之间新增 模块(Module) 层级,通过 module-info.java 声明依赖和导出。JDK 自身被拆分为 70-90 个独立模块。
2.5 LTS 时代:JDK 11 / 17 / 21
| Java 8 | 2014.03 | Lambda、Stream(LTS) |
| Java 11 | 2018.09 | 模块化成熟、HTTP Client、移除 Java EE(LTS) |
| Java 17 | 2021.09 | 密封类、Spring Boot 3.0 最低要求(LTS) |
| Java 21 | 2023.09 | 虚拟线程(LTS) |
三、OpenJDK 与 OracleJDK 何时分岔?收费为何还有人选?还有哪些厂商发行版?
3.1 何时开始不一样?
从 JDK 7 开始源码基本一致,真正的分水岭是 JDK 11——Oracle 停止提供独立 JRE,改变授权模式。
3.2 收费为何还有人选?
-
Oracle 的 "一站式"商业支持
-
法律保障(indemnification) ——专利诉讼保护
-
企业有预算,需要长期稳定支持
3.3 还有哪些厂商发行版?
| Eclipse 基金会 | Adoptium Temurin | 社区驱动,前身 AdoptOpenJDK |
| Amazon | Corretto | AWS 生产验证,免费 |
| Azul | Zulu / Zing | 商业版有 C4 垃圾回收器 |
| Microsoft | Microsoft Build of OpenJDK | 官方支持 |
| IBM | Semeru | 基于 OpenJ9,云优化 |
| Red Hat | Red Hat Build of OpenJDK | 企业级支持 |
全部基于 GPL v2,免费用于生产环境。
四、高版本 JDK 如何选?LTS 还是非 LTS?OpenJDK 还是厂商发行版?
4.1 必须选 LTS
非 LTS 版本(如 9、10、12-20)只提供 6 个月安全补丁,生产环境必须用 LTS。
| 维护老项目 | Java 8 | 生态最成熟 |
| 企业新项目 | Java 17 | Spring Boot 3.0 最低要求 |
| 技术前沿 | Java 21 | 虚拟线程革命性特性 |
4.2 选厂商发行版,不选 Oracle OpenJDK 官方版
-
Oracle OpenJDK 官方版只提供半年更新
-
厂商发行版免费且长期支持:Temurin、Corretto、Zulu 等
-
Amazon Corretto 经过 AWS 生产验证
五、JDK 9 模块化后目录结构变了什么?jmods 和 lib 各有什么用?
5.1 JDK 8 vs JDK 9+ 目录对比
| 独立 JRE | ✅ jre/ | ❌ 已移除 |
| 核心类库 | lib/rt.jar | 拆分为 jmods/*.jmod |
| tools.jar | ✅ 存在 | ❌ 已移除 |
| 配置文件 | 分散各处 | 集中到 conf/ |
5.2 jmods 和 lib 的分工
-
jmods/:构建时素材库,供 jlink 裁剪镜像。JVM 运行时不读取它。
-
lib/:运行时核心。其中的 modules 文件是内部二进制格式,包含所有标准库的 .class 字节码。JVM 启动时读取的就是它。
六、JDK 模块化 vs OSGi:为什么 JPMS 不支持同名包而 OSGi 支持?
6.1 OSGi 是什么?
OSGi(2000 年代初)是 Java 模块化的事实标准,每个 bundle 通过 MANIFEST.MF 声明依赖,支持运行时热插拔。Eclipse IDE 是典型应用。
6.2 核心差异
| 本质 | JVM 内置特性 | 第三方框架 |
| 配置 | module-info.java(编译时) | MANIFEST.MF(运行时) |
| 动态性 | 静态,启动时确定 | 动态,支持热插拔 |
| 类加载架构 | 分层 | 网状(每个 bundle 独立 ClassLoader) |
6.3 为什么 JPMS 禁止同名包,而 OSGi 允许?
-
OSGi:每个 bundle 有独立的 ClassLoader。JVM 中类的唯一标识是 (ClassLoader + 类全名) ,同名类由不同 ClassLoader 加载就是不同类,可以共存。
-
JPMS:语言级模块化,编译时就强制包唯一性。设计哲学是 "宁可启动失败,也不要运行时存在歧义" 。
七、JDK 9+ 为什么不带 JRE 了?运行时从哪来?为什么还有独立 JRE 下载?
7.1 为什么不带了?
模块化让 JRE 从"固定产物"变成"可按需组装"。开发者用 jlink 按需裁剪,不再需要臃肿的通用 JRE。
7.2 运行时从哪来?
lib/modules 文件就是运行时的核心——它包含了所有标准库模块的 .class 字节码,JVM 启动时直接读取它。
7.3 为什么还有独立 JRE 下载?
第三方厂商(如 Adoptium)仍提供 JRE 格式下载,满足历史遗留部署需求。官方推荐用 jlink 自建精简运行时:
bash
jlink -p $JAVA_HOME/jmods –add-modules java.base –output myjre
八、JDK 21 虚拟线程的本质和原理是什么?
8.1 本质
虚拟线程是 JVM 调度的轻量级线程,不再 1:1 映射 OS 线程,而是通过 载体线程(Carrier Threads) 复用 OS 线程资源。
8.2 三大核心机制
① M:N 调度:M 个虚拟线程调度到 N 个载体线程(默认 N = CPU 核心数)上执行。
② 挂载/卸载:虚拟线程阻塞 I/O 时,自动从载体线程卸载,栈数据复制到堆内存,载体线程立即释放去执行其他任务;I/O 完成时重新挂载恢复执行。阻塞不再浪费 OS 线程。
③ Continuation(续体):底层通过 Continuation 保存/恢复执行状态(栈帧、局部变量),实现"暂停-恢复"。
8.3 与平台线程对比
| 映射 | 1:1 | M:N |
| 创建成本 | 高(1MB 栈) | 极低(几百字节) |
| 切换成本 | 微秒级(内核态) | 纳秒级(用户态) |
| 数量上限 | 几千 | 数百万 |
8.4 使用方式
java
// 方式1:直接创建
Thread.startVirtualThread(() -> System.out.println("Hello!"));
// 方式2:ExecutorService(推荐)
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> { Thread.sleep(1000); return "Done"; });
}
8.5 注意事项
-
不要池化虚拟线程(创建成本极低)
-
谨慎使用 synchronized(可能导致虚拟线程被"钉住"无法卸载)
-
谨慎使用 ThreadLocal(数百万虚拟线程可能 OOM)
九、javax 包为什么被移除?哪些功能没了?由谁维护?
9.1 为什么移除?
2017 年 Oracle 将 Java EE 捐赠给 Eclipse 基金会,更名为 Jakarta EE。为了摆脱 Oracle 对 javax.* 命名空间的控制,Eclipse 决定将包名从 javax.* 改为 jakarta.*。
注意:javax.sql.*、javax.crypto.* 等属于 Java SE 自身,不会被移除。
9.2 哪些被移除了?(JDK 11)
| java.xml.ws | JAX-WS(Web Service) |
| java.xml.bind | JAXB(XML 绑定) |
| java.corba | CORBA |
| java.transaction | JTA(事务) |
| java.activation | JAF(MIME 处理) |
| java.se.ee | 上述模块的聚合 |
此外,Java Applet、Java Web Start、JavaFX 也被移除。
9.3 由谁维护?
被移除的 Java EE 模块由 Eclipse 基金会 以 Jakarta EE 名义维护,以 jakarta.* 命名空间发布。
JDK 11+ 如需使用,手动引入依赖:
xml
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.0</version>
</dependency>
十、Java 标准 API 和内部 API 有什么区别?
10.1 标准 API
Java 平台规范中定义和承诺的公共 API,所有 JDK 实现都必须提供,跨版本向后兼容。
-
主要命名空间:java.*、部分 javax.*
-
示例:java.util.ArrayList
10.2 内部 API
JDK 的内部实现细节,不属于规范,不同 JDK 实现可能不同或缺失,可能随时移除,无向后兼容保证。
-
主要命名空间:sun.*、大部分 com.sun.*
-
示例:sun.misc.Unsafe
10.3 两个特例
-
sun.misc 和 sun.reflect 由 jdk.unsupported 模块导出
-
sun.misc.Unsafe 被大量框架依赖,JDK 暂时保留可访问性,但仍是内部 API
10.4 JDK 9 强封装
从 JDK 9 开始,模块化系统要求:只有导出(exported)或开放(opened)的包才能被外部访问,其余默认不可访问。
10.5 开发建议
使用 java.*,避免 sun.*,谨慎使用 com.sun.*。
可用 jdeprscan 工具扫描代码中是否使用了已弃用或已移除的 API。
写在最后
Java 30 年,从"一次编写,到处运行"到虚拟线程百万并发,每一步都在解决上一代的痛点。
版本选择:
-
维护老项目 → Java 8
-
企业新项目 → Java 17
-
技术前沿 → Java 21
JDK 选择:
-
生产环境 → Adoptium Temurin 或 Amazon Corretto
-
需要商业支持 → Azul Zulu 或 Oracle JDK
技术选型没有标准答案,适合自己业务场景的,才是最好的。
如果觉得文章对你有帮助,欢迎点赞、收藏、转发!有问题可以在评论区留言讨论。






