将基于 Oracle JDK 17 开发的 Spring Boot 3.2.12 项目迁移到 OpenJDK 17 环境

发布于:2025-09-14 ⋅ 阅读:(20) ⋅ 点赞:(0)

将基于 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)
  1. 更换 JDK:将你的本地开发机器、测试服务器以及 CI/CD 流水线(如 Jenkins, GitLab CI)上的 JDK 从 Oracle JDK 17 替换为 OpenJDK 17。

  2. 更新构建工具配置

    • 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. 验证测试

完成上述配置更改后,进行全面的测试是至关重要的。

  1. 本地测试:在安装好 OpenJDK 17 的本地环境中,运行 mvn clean compile 或 gradle compileJava 确保编译通过。

  2. 单元测试:运行 mvn test 或 gradle test,确保所有单元测试通过。

  3. 集成测试/功能测试:启动应用,进行完整的端到端测试,确保所有核心功能正常。

  4. 性能测试(可选):如果你对性能有极致要求,可以进行简单的压测,对比在 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.servletjavax.persistence (JPA), javax.annotation (如 @PostConstruct), javax.ejbjavax.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 的问题。

结论与操作指南

  1. OpenJDK 17 有 javax 包吗?

    • :核心的 javax 包(如 javax.swingjavax.sql)是存在的。

    • 没有:企业级的 javax 包(如 javax.servlet)已从 JDK 中移除。

  2. 你的 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)。

  3. 如果遇到 ClassNotFoundException 或 NoClassDefFoundError 怎么办?
    这通常意味着你的某个依赖项还在尝试使用旧的 javax EE 包。你需要:

    • 升级这个依赖到与 Jakarta EE 9+ 兼容的版本。

    • 或者,如果这个依赖没有新版本,你可以尝试添加一个适配器库(例如 org.eclipse.ee4j:jakartaee-api),但这是一个临时方案,最好还是寻找替代依赖。

总结表格:

包类型 示例 OpenJDK 17 中是否存在? 在 Spring Boot 3 中如何获取?
核心 javax javax.swingjavax.sql  (JDK 内置) JDK 自带,无需处理
Java EE javax javax.servletjavax.persistence  (已从 JDK 移除) 已过时,应使用对应的 jakarta.* 包
Jakarta EE jakarta.servletjakarta.persistence  (独立规范) 通过 Spring Boot Starters 自动引入

因此,对于你的迁移,无需担心 javax 包的问题。你只需要确保项目正确使用了 jakarta.* 命名空间,并且依赖管理正确,OpenJDK 17 就能完美运行。

📦 javax.sql 包的核心成员

javax.sql 包从 JDK 1.4 开始就成为了 Java SE 平台的一部分,提供了许多用于访问和处理服务器端数据源的关键 API。

为了让你快速了解 javax.sql 包的核心内容,我整理了下面的表格:

类别 主要接口/类 说明
核心接口 DataSource 替代 DriverManager 建立连接的工厂,是获取连接的首选方式。
连接池 ConnectionPoolDataSourcePooledConnection 支持连接池和语句池,可以显著提升性能。
分布式事务 XADataSourceXAConnection 支持分布式事务,允许在单个事务中涉及多个服务器上的数据源。
行集 (Rowsets) RowSetRowSetMetaData 提供更灵活的方式来处理结果集,尤其适用于断开连接的环境。

🔄 与 Oracle JDK 的兼容性

在 javax.sql.DataSource 这个问题上,OpenJDK 17 和 Oracle JDK 17 的行为是完全一致的。两者都包含了标准的 javax.sql 包。
![[Pasted image 20240909092144.png]]
这意味着:

  • 你的代码无需修改:所有依赖于 javax.sql.DataSource 的代码在 OpenJDK 17 上都能正常运行。

  • 依赖关系不变:你不需要额外引入任何 JAR 包来弥补 JDK 本身的缺失。

⚠️ 注意事项:实现与使用

虽然接口是标准化的,但需要注意以下几点:

  1. JDK 提供接口,而非实现:JDK 自带的 javax.sql.DataSource 只是一个接口,不是具体的实现。你需要通过第三方库(如 HikariCPApache Commons DBCPTomcat JDBC Pool 等)来获得实际的、功能完备的数据源和连接池实现。应用服务器(如 Tomcat, WildFly 等)通常会为你集成这些实现。

  2. 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 提供了一个在技术、法律和商业上都近乎完美的选择

  1. 可靠:100% 通过 TCK,确保与 Java 标准完全兼容。

  2. 中立:由基金会管理,避免供应商锁定。

  3. 免费:清晰的开源许可,可用于所有环境而无法律风险。

  4. 流行:拥有强大的社区支持和广泛的工具链集成,遇到问题容易找到解决方案。

因此,当你有“选择一个 OpenJDK”的需求时,Eclipse Temurin 应该作为你的默认首选。只有在你有特定云平台(如 AWS, Azure)的深度集成需求,或者需要某些特定供应商提供的特殊功能(如 Azul 的 GC)时,才需要考虑其他发行版。