将基于 Oracle JDK 17 开发的 Spring Boot 3.2.12 项目迁移到 OpenJDK 17 环境是一个非常直接和常见的过程,因为两者在绝大多数场景下是完全兼容的。Spring Boot 3.2 本身的要求就是 JDK 17+,它并不区分 Oracle JDK 还是 OpenJDK。
你的改造工作主要集中在环境配置、构建工具和依赖管理上,而不是大量的代码修改。
以下是详细的步骤和注意事项:
1. 核心兼容性确认(通常没问题)
首先,最重要的是要明白:OpenJDK 是 Java SE 规范的开源参考实现,而 Oracle JDK 17 及以后版本正是由 OpenJDK 构建而来,并附加了一些非核心的商业功能。
从 JDK 11 以后,Oracle JDK 和 OpenJDK 在功能上几乎完全一致,尤其是对于绝大多数应用开发而言。因此,你的代码在编译和运行时几乎不需要任何修改。
2. 改造步骤
a. 开发与构建环境 (CI/CD)
更换 JDK:将你的本地开发机器、测试服务器以及 CI/CD 流水线(如 Jenkins, GitLab CI)上的 JDK 从 Oracle JDK 17 替换为 OpenJDK 17。
下载:可以从多个供应商获取 OpenJDK 17 二进制发行版,推荐选择:
Eclipse Temurin (推荐): https://adoptium.net/temurin/releases/
Amazon Corretto: https://aws.amazon.com/cn/corretto/
Azul Zulu: https://www.azul.com/downloads/
Microsoft Build of OpenJDK: https://www.microsoft.com/openjdk
这些发行版都经过了良好的测试,与 Oracle JDK 17 100% 兼容。
更新构建工具配置:
Maven:
确保你的pom.xml
中的maven-compiler-plugin
配置的<source>
和<target>
都是17
。xml
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <source>17</source> <target>17</target> <encoding>UTF-8</encoding> </configuration> </plugin>
你也可以通过
properties
配置:xml
<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <maven.compiler.release>17</maven.compiler.release> <!-- 推荐使用 release 参数 --> </properties>
Gradle:
在build.gradle
中确保编译选项正确:groovy
java { sourceCompatibility = '17' targetCompatibility = '17' }
b. Docker 化部署(如果适用)
如果你的项目通过 Docker 容器部署,需要将 Dockerfile 中的基础镜像从 Oracle JDK 镜像切换为 OpenJDK 镜像。
之前可能用的 (Oracle JDK):
dockerfile
FROM container-registry.oracle.com/java/jdk:17 ...
或者一些旧的
oracle/openjdk
镜像(已废弃)。修改为 (OpenJDK):
强烈推荐使用 Eclipse Temurin 的镜像:dockerfile
FROM eclipse-temurin:17-jdk-jammy ...
或者使用其他供应商的镜像,如:
dockerfile
FROM amazoncorretto:17 ...
dockerfile
FROM azul/zulu-openjdk:17 ...
对于生产环境,通常建议使用 JRE 而不是完整的 JDK,以减少镜像大小和攻击面:
dockerfile
FROM eclipse-temurin:17-jre-jammy ...
注意:从 JDK 17 开始,Oracle 不再提供独立的 JRE 安装包,但大多数 OpenJDK 发行版(如 Temurin)仍然提供基于 JDK 的精简 JRE 镜像。
c. 检查特定依赖和功能
虽然极其罕见,但仍需检查你的项目是否使用了极其小众的、仅限 Oracle JDK 的商业特性:
Java Flight Recorder (JFR): 在 OpenJDK 17 中,JFR 已经是开源功能!你可以像在 Oracle JDK 中一样使用它。这是最大的一个变化,以前它是商业特性。
Java Mission Control (JMC): 虽然 JFR 开源了,但 JMC 工具本身是分开的。你需要从其他渠道获取 compatible 版本的 JMC。
其他商业特性: 如 Jaotc (AOT) 已经被移除,所以基本无需考虑。像 AppCDS 这类功能在 OpenJDK 发行版中通常也是可用的。
如果你的项目没有明确引入这些特性,那么你可以完全忽略这一点。
3. 验证测试
完成上述配置更改后,进行全面的测试是至关重要的。
本地测试:在安装好 OpenJDK 17 的本地环境中,运行
mvn clean compile
或gradle compileJava
确保编译通过。单元测试:运行
mvn test
或gradle test
,确保所有单元测试通过。集成测试/功能测试:启动应用,进行完整的端到端测试,确保所有核心功能正常。
性能测试(可选):如果你对性能有极致要求,可以进行简单的压测,对比在 OpenJDK 和 Oracle JDK 下的表现。但对于绝大多数应用,性能差异可以忽略不计。
总结
方面 | 改造动作 |
---|---|
JDK 安装包 | 将 Oracle JDK 17 替换为 OpenJDK 17 发行版(如 Eclipse Temurin 17) |
构建配置 | 确认 Maven/Gradle 的编译级别为 17 |
Docker 镜像 | 将基础镜像从 Oracle JDK 镜像改为 eclipse-temurin:17-jdk-jammy 或 eclipse-temurin:17-jre-jammy |
特性依赖 | (基本无需操作) 检查是否依赖极少数已不再受限的商业功能(大概率没有) |
测试 | 进行全面测试:编译、单元测试、功能测试 |
总而言之,这个迁移过程非常平滑,90% 的工作就是更换 JDK 安装包和 Docker 镜像,剩下的 10% 是充分的测试。 你可以自信地进行操作。
1. 核心 javax
包 vs. Java EE javax
包
首先要区分两种 javax
包:
核心
javax
包:例如javax.swing
(GUI工具包),javax.sql
(数据库连接),javax.security
(安全相关) 等。这些是 Java SE 平台的一部分,在 OpenJDK 17 中仍然存在。Java EE / Jakarta EE
javax
包:例如javax.servlet
,javax.persistence
(JPA),javax.annotation
(如@PostConstruct
),javax.ejb
,javax.xml.bind
(JAXB) 等。这些原本是 Java 企业版平台的一部分。
2. 关键变化:JDK 9 的模块化 (JEP 320)
从 JDK 9 开始,Oracle 和 OpenJDK 社区通过 JEP 320 决定了一项重要变更:将 Java EE 和 CORBA 模块从 JDK 中移除。
这意味着:
在 JDK 8 中:这些 Java EE 的
javax
包是 随 JDK 一起分发 的。在 JDK 9+(包括 JDK 17)中:这些 Java EE 的
javax
包 不再随 JDK 一起分发。如果你需要使用这些功能,你必须像添加其他第三方库一样,手动地将它们作为依赖项添加到你的项目中。
3. 这对 Spring Boot 3.2.12 项目意味着什么?
Spring Boot 3 是基于 Jakarta EE 9+ 的,这是一个关键信息!
命名空间迁移:Jakarta EE 9 进行了一个重大的更名,将所有
javax.*
包名都改为了jakarta.*
。例如:
javax.servlet
->jakarta.servlet
javax.persistence
->jakarta.persistence
Spring Boot 自动配置:Spring Boot starter(如
spring-boot-starter-web
)已经为你自动处理了这些依赖。当你引入spring-boot-starter-web
时,它会自动拉取正确版本的 Jakarta Servlet API (jakarta.servlet:jakarta.servlet-api
),你不需要再手动担心javax.servlet
的问题。
结论与操作指南
OpenJDK 17 有
javax
包吗?有:核心的
javax
包(如javax.swing
,javax.sql
)是存在的。没有:企业级的
javax
包(如javax.servlet
)已从 JDK 中移除。
你的 Spring Boot 3.2.12 项目需要做什么?
代码中的
import
语句:检查你的代码。由于你使用的是 Spring Boot 3,所有之前对javax.*
(EE) 的导入都应该已经被改为jakarta.*
了。这是升级到 Spring Boot 3 的必要步骤。如果你的代码里还有import javax.servlet...
,那说明项目没有正确升级,需要改为import jakarta.servlet...
。项目依赖:确保你的
pom.xml
或build.gradle
中的依赖都是正确的 Spring Boot 3 starters。Spring Boot 会帮你管理所有 Jakarta EE 依赖。你不需要也不应该手动添加旧的javax
依赖(如javax.servlet:javax.servlet-api
)。
如果遇到
ClassNotFoundException
或NoClassDefFoundError
怎么办?
这通常意味着你的某个依赖项还在尝试使用旧的javax
EE 包。你需要:升级这个依赖到与 Jakarta EE 9+ 兼容的版本。
或者,如果这个依赖没有新版本,你可以尝试添加一个适配器库(例如
org.eclipse.ee4j:jakartaee-api
),但这是一个临时方案,最好还是寻找替代依赖。
总结表格:
包类型 | 示例 | OpenJDK 17 中是否存在? | 在 Spring Boot 3 中如何获取? |
---|---|---|---|
核心 javax |
javax.swing , javax.sql |
是 (JDK 内置) | JDK 自带,无需处理 |
Java EE javax |
javax.servlet , javax.persistence |
否 (已从 JDK 移除) | 已过时,应使用对应的 jakarta.* 包 |
Jakarta EE | jakarta.servlet , jakarta.persistence |
否 (独立规范) | 通过 Spring Boot Starters 自动引入 |
因此,对于你的迁移,无需担心 javax
包的问题。你只需要确保项目正确使用了 jakarta.*
命名空间,并且依赖管理正确,OpenJDK 17 就能完美运行。
📦 javax.sql 包的核心成员
javax.sql
包从 JDK 1.4 开始就成为了 Java SE 平台的一部分,提供了许多用于访问和处理服务器端数据源的关键 API。
为了让你快速了解 javax.sql
包的核心内容,我整理了下面的表格:
类别 | 主要接口/类 | 说明 |
---|---|---|
核心接口 | DataSource |
替代 DriverManager 建立连接的工厂,是获取连接的首选方式。 |
连接池 | ConnectionPoolDataSource , PooledConnection |
支持连接池和语句池,可以显著提升性能。 |
分布式事务 | XADataSource , XAConnection |
支持分布式事务,允许在单个事务中涉及多个服务器上的数据源。 |
行集 (Rowsets) | RowSet , RowSetMetaData |
提供更灵活的方式来处理结果集,尤其适用于断开连接的环境。 |
🔄 与 Oracle JDK 的兼容性
在 javax.sql.DataSource
这个问题上,OpenJDK 17 和 Oracle JDK 17 的行为是完全一致的。两者都包含了标准的 javax.sql
包。
![[Pasted image 20240909092144.png]]
这意味着:
你的代码无需修改:所有依赖于
javax.sql.DataSource
的代码在 OpenJDK 17 上都能正常运行。依赖关系不变:你不需要额外引入任何 JAR 包来弥补 JDK 本身的缺失。
⚠️ 注意事项:实现与使用
虽然接口是标准化的,但需要注意以下几点:
JDK 提供接口,而非实现:JDK 自带的
javax.sql.DataSource
只是一个接口,不是具体的实现。你需要通过第三方库(如 HikariCP、Apache Commons DBCP、Tomcat JDBC Pool 等)来获得实际的、功能完备的数据源和连接池实现。应用服务器(如 Tomcat, WildFly 等)通常会为你集成这些实现。Spring Boot 的自动配置:如果你在使用 Spring Boot,它通常会自动配置一个高性能的连接池(如 HikariCP)。你只需要在
application.properties
或application.yml
中配置数据库连接字符串、用户名、密码等属性即可,Spring Boot 会帮你创建和管理实际的DataSource
实例。
💡 总结
你可以放心地在 OpenJDK 17 中使用
javax.sql.DataSource
,其行为与 Oracle JDK 17 无任何差异。你看到的这个接口是 Java SE 的标准 API,并非来自 Java EE/Jakarta EE。
在实际项目中,你通常会通过配置第三方连接池库(或由 Spring Boot 等框架自动配置)来获得这个接口的具体实现。
推荐 Eclipse Temurin 的 OpenJDK 发行版,是基于其在技术可靠性、生态中立性、许可友好性和社区支持等多个维度的综合优势。
以下是详细的原因,解释了为什么 Eclipse Temurin 通常是基于 OpenJDK 构建的 Java 应用程序的首选:
1. 技术可靠性与认证:通过 TCK 验证
这是最核心、最关键的原因。
什么是 TCK? TCK (Technology Compatibility Kit) 是一套庞大的测试套件,用于验证某个 Java 实现是否完全符合 Java SE 平台规范。只有通过了 TCK 测试,才能合法地称为“Java”。
Temurin 的承诺:Eclipse Temurin 的每一个构建版本都严格通过 Java SE TCK 测试。这意味着你可以 100% 确信其与 Oracle JDK 在功能上是完全兼容的,你的应用程序从 Oracle JDK 迁移到 Temurin 不会出现因 JDK 本身实现差异而导致的诡异问题。
对比:虽然许多其他发行版也声称通过 TCK,但 Temurin 将此作为其最核心的、公开透明的承诺,其测试流程由开源社区监督,极大地增强了可信度。
2. 生态中立性与厂商锁定规避
由基金会管理,而非单一公司:Temurin 项目由 Eclipse 基金会 下的 Adoptium 工作组(前身为 AdoptOpenJDK)管理。Eclipse 基金会是一个中立的、非盈利的组织,其治理模式确保了项目不会被任何单一商业公司的利益所主导。
避免供应商锁定:选择 Temurin 意味着你依赖于一个由社区驱动、多家公司(包括 IBM, Red Hat, Microsoft, Azul,阿里云等)共同支持的项目,而不是绑定到某一家云厂商或商业公司的JDK。这为你提供了更大的灵活性和未来的选择权。
3. 许可友好性:完全免费且无陷阱
纯净的许可证:Temurin 在GPLv2 with Classpath Exception 许可证下提供。这是一个非常友好的开源许可证,允许你自由地使用、分发甚至将其与你的专有软件一起打包和分发,而无需开源你的业务代码。
无商业条款陷阱:与某些供应商的发行版可能包含的潜在商业条款或限制不同,Temurin 的许可非常清晰和纯粹,让你可以毫无法律风险地用于任何环境(开发、测试、生产)。
4. 广泛的社区支持与认可
悠久的历史和信任:Temurin 是原 AdoptOpenJDK 项目的延续,该项目在社区中积累了极高的声誉和信任度,是许多开发者和公司从 Oracle JDK 迁移时的第一选择。
广泛的工具链集成:正是由于其受欢迎程度和可靠性,许多主流工具都为其提供了“开箱即用”的支持。
SDKMAN!: 一个流行的 JVM 生态工具管理器中,Temurin 是默认的 JDK 提供商。
IDE 集成:如 IntelliJ IDEA 和 Visual Studio Code 的 Java 扩展包都直接推荐或集成 Temurin 的安装。
CI/CD 集成:如 GitHub Actions 官方就有
actions/setup-java@v4
Action,可以轻松一键安装 Temurin JDK。
5. 丰富的版本和构建选择
Temurin 提供了非常全面和灵活的下载选择:
多种版本:不仅提供最新的 LTS(如 8, 11, 17, 21)和短期版本,还提供这些版本的更新(例如 17.0.11, 21.0.3 等)。
多种架构:支持 x86_64 (Intel/AMD), AArch64 (ARM64, 如 Apple Silicon Mac, AWS Graviton), ppc64le, s390x 等。
多种镜像类型:提供 JDK(开发包)、JRE(运行环境)以及用于容器环境的
jlink
优化的最小化 JRE 镜像。
Temurin vs. 其他流行 OpenJDK 发行版
发行版 | 主要优势 | 潜在考虑 |
---|---|---|
Eclipse Temurin | 生态中立、TCK认证、许可友好、社区强大 | 通常是无脑首选的最佳平衡点 |
Oracle JDK | 官方构建,与最新功能/修复同步最快 | 生产环境使用需要付费订阅(除非只用其提供的免费 GraalVM EE) |
Amazon Corretto | 由 AWS 提供和维护,与 AWS 服务集成体验好 | 与 AWS 生态绑定较深,是单一供应商产品 |
Azul Zulu | 提供多种构建,包括领先的 GC 方案 | 商业公司 Azul Systems 主导,社区中立性不如 Temurin |
Microsoft Build of OpenJDK | 由微软优化和维护,对 Azure 和 Windows 优化 | 相对较新,生态和社区影响力仍在发展中 |
总结:为什么推荐 Temurin?
对于绝大多数开发者和企业,尤其是从 Oracle JDK 迁移的场景,Eclipse Temurin 提供了一个在技术、法律和商业上都近乎完美的选择:
可靠:100% 通过 TCK,确保与 Java 标准完全兼容。
中立:由基金会管理,避免供应商锁定。
免费:清晰的开源许可,可用于所有环境而无法律风险。
流行:拥有强大的社区支持和广泛的工具链集成,遇到问题容易找到解决方案。
因此,当你有“选择一个 OpenJDK”的需求时,Eclipse Temurin 应该作为你的默认首选。只有在你有特定云平台(如 AWS, Azure)的深度集成需求,或者需要某些特定供应商提供的特殊功能(如 Azul 的 GC)时,才需要考虑其他发行版。