JDK 17/21为何不再包含JRE及手动生成方法

📅 2026/7/21 12:07:03 👁️ 阅读次数 📝 编程学习
JDK 17/21为何不再包含JRE及手动生成方法

1. JDK安装后为何缺少JRE文件夹

在JDK 17和21版本中,Oracle对Java的打包方式进行了重大调整。传统JDK安装包会同时包含开发工具(JDK)和运行时环境(JRE)两个独立目录,但从JDK 11开始,这种结构发生了变化。

1.1 模块化系统的引入

Java 9引入的模块化系统(Jigsaw项目)是这一变化的根本原因。模块化后,JRE不再是独立实体,而是作为JDK的一个子集存在。具体表现为:

  • JDK镜像现在包含完整的Java SE规范实现
  • 运行时环境(JRE)的功能已集成到JDK的jmods目录中
  • 通过jlink工具可以按需创建自定义运行时镜像

1.2 实际目录结构对比

以Windows平台为例,传统JDK 8和现代JDK 17/21的目录结构差异明显:

JDK 8典型结构: ├── jdk1.8.0_291 │ ├── bin # 开发工具 │ ├── jre # 独立运行时 │ └── lib # 类库 └── jre1.8.0_291 # 独立安装的JRE JDK 17/21典型结构: ├── jdk-17.0.10 │ ├── bin # 开发工具 │ ├── conf # 配置文件 │ ├── include # 本地头文件 │ ├── jmods # 模块化组件 │ └── legal # 许可信息

2. 手动生成JRE文件夹的三种方法

2.1 使用jlink工具创建精简运行时

这是Oracle官方推荐的方式,可以生成完全符合需求的JRE:

# 进入JDK安装目录 cd "C:\Program Files\Java\jdk-21.0.10" # 创建最小化JRE(约40MB) bin\jlink.exe --module-path jmods --add-modules java.base --output jre-minimal # 创建标准JRE(包含常用模块) bin\jlink.exe --module-path jmods \ --add-modules java.base,java.desktop,java.sql \ --output jre-standard

关键参数说明:

  • --module-path:指定模块源路径
  • --add-modules:选择要包含的模块
  • --output:输出目录名称

2.2 通过安装程序生成传统JRE

虽然官方不推荐,但仍可通过以下步骤生成传统JRE:

  1. 以管理员身份打开命令提示符
  2. 执行以下命令:
    cd "C:\Program Files\Java\jdk-21.0.10" bin\jlink.exe --module-path jmods --add-modules ALL-MODULE-PATH --output jre-full
  3. 这会在JDK目录下创建完整的jre-full文件夹

2.3 复制法创建兼容性JRE(适用于老旧软件)

某些遗留系统可能严格要求传统JRE结构,可以这样处理:

# 创建基础目录结构 mkdir jre-legacy mkdir jre-legacy\bin mkdir jre-legacy\lib # 复制必要文件 xcopy /s /y bin\server jre-legacy\bin\server xcopy /s /y lib\* jre-legacy\lib\ copy bin\java.exe jre-legacy\bin\ copy bin\javaw.exe jre-legacy\bin\

3. 环境变量配置的注意事项

3.1 标准配置方案

无论采用哪种JRE生成方式,环境变量都应指向JDK目录:

JAVA_HOME=C:\Program Files\Java\jdk-21.0.10 PATH=%JAVA_HOME%\bin;...

3.2 特殊场景配置

如果某些应用必须使用独立JRE路径,可以这样设置:

# 使用jlink生成的JRE JRE_HOME=%JAVA_HOME%\jre-standard # 使用复制法生成的JRE JRE_HOME=%JAVA_HOME%\jre-legacy

3.3 常见配置误区

  1. 路径冲突:避免同时配置JAVA_HOME和JRE_HOME指向不同版本
  2. 符号链接问题:Windows快捷方式不是真正的符号链接,建议使用完整路径
  3. 系统变量vs用户变量:开发环境建议配置系统变量

4. 验证与问题排查

4.1 基础验证步骤

# 验证Java版本 java -version # 验证编译器 javac -version # 检查模块系统 java --list-modules

4.2 典型问题解决方案

问题1:找不到或无法加载主类

可能原因:

  • 类路径未正确设置
  • 模块路径冲突

解决方案:

# 明确指定类路径 java -cp bin;lib/* com.example.Main # 或指定模块路径 java -p mods -m module/package.Main

问题2:jlink生成的JRE无法运行GUI程序

缺少必要模块:

# 重新生成包含GUI模块的JRE jlink --module-path jmods \ --add-modules java.desktop,java.base \ --output jre-with-gui

问题3:与旧版JDK共存时的冲突

推荐处理方式:

  1. 卸载所有旧版Java
  2. 使用工具管理多版本:
    # 使用jenv工具(需先安装) jenv add /path/to/jdk17 jenv add /path/to/jdk21 jenv global 21

5. 高级应用场景

5.1 创建平台专属运行时

针对特定硬件优化:

jlink --module-path jmods \ --add-modules java.base,java.desktop \ --output jre-arm64 \ --vm=server \ --strip-debug \ --no-header-files \ --no-man-pages

5.2 构建Docker镜像优化

Dockerfile示例:

FROM eclipse-temurin:21-jdk-jammy AS builder RUN jlink --module-path $JAVA_HOME/jmods \ --add-modules java.base,java.logging \ --strip-debug \ --no-man-pages \ --output /opt/jre-minimal FROM ubuntu:22.04 COPY --from=builder /opt/jre-minimal /opt/jre ENV PATH="/opt/jre/bin:$PATH"

5.3 性能调优建议

  1. 精简运行时大小:
    jlink --compress=2 --no-header-files ...
  2. 预生成类数据共享存档:
    java -Xshare:dump -XX:+UseAppCDS
  3. 选择适合的VM实现:
    jlink --vm=client # 对GUI应用更友好 jlink --vm=server # 对服务端应用更优

对于需要兼容传统部署方式的场景,建议在持续集成流程中加入jlink步骤,自动生成符合要求的JRE分发包。现代Java应用更推荐直接使用JDK内置的运行时能力,而非维护独立的JRE副本。