努力
加油

Debian或Ubuntu镜像如何预装Java开发工具包JDK?

在 Debian 或 Ubuntu 服务器上预装 JDK,最稳妥且符合“云原生”规范的做法,绝不是去 Oracle 官网下载 .tar.gz 手动解压配置环境变量(除非你有特殊的商业授权需求),而是直接使用系统包管理器安装开源发行版。

目前业界主流、合规且零成本的选择是 OpenJDK。以下分两种场景说明:自动化部署(镜像构建)和手动服务器配置。


一、 核心原则:为什么选 OpenJDK?

  1. 合规性:Oracle JDK 8u161 之后版本需要订阅协议,企业商用需付费。OpenJDK 完全开源免费,无法律风险。
  2. 维护性:通过 apt 安装的包,后续安全补丁由 Ubuntu/Debian 官方源自动推送,无需人工干预。
  3. 兼容性:Java 应用对 OpenJDK 和 Oracle JDK 的二进制兼容性极高,绝大多数业务代码无感知切换。

推荐版本:

  • Java 8 (LTS):openjdk-8-jdk
  • Java 11 (LTS):openjdk-11-jdk
  • Java 17 (LTS):openjdk-17-jdk
  • Java 21 (最新 LTS):openjdk-21-jdk

二、 场景一:制作自定义云服务器镜像(预装)

如果你在使用阿里云、腾讯云、AWS 等云平台,希望创建自己的自定义镜像(Custom Image),让所有基于该镜像启动的 ECS/CVM 实例都自带 JDK,请按以下步骤操作:

步骤 1:在一台干净的 Debian/Ubuntu 虚拟机中执行安装

登录到用于制作镜像的基础系统,执行以下命令:

# 更新软件源
sudo apt update

# 安装 OpenJDK 17(根据实际需求替换版本号)
sudo apt install -y openjdk-17-jdk-headless

# 验证安装
java -version
javac -version

注意:生产环境建议安装 -jre-headless 或 -jdk-headless 版本,避免安装不必要的 GUI 库,减小镜像体积并提升安全性。

步骤 2:清理痕迹(关键!)

在打包镜像前,必须清理系统日志、临时文件、SSH host keys 等敏感信息,否则会导致每台新机器 SSH 警告或泄露历史数据。

# 清理 apt 缓存
sudo apt clean

# 删除 SSH host keys(新机器启动时会重新生成)
sudo rm -f /etc/ssh/ssh_host_*

# 清空历史记录
history -c
cat /dev/null > ~/.bash_history

# 可选:使用 cloud-init 清理工具(如果使用了 cloud-init)
sudo cloud-init clean --logs

步骤 3:制作镜像

  • 阿里云:控制台 -> 镜像与实例 -> 自定义镜像 -> 创建自定义镜像。
  • 腾讯云:控制台 -> 镜像 -> 自定义镜像 -> 创建自定义镜像。
  • 本地 KVM/QEMU:使用 virt-sysprep 工具清理后打包。

这样生成的镜像,每次启动时都会自动包含已配置的 JDK 环境。


三、 场景二:手动在已有服务器上安装 JDK

如果你已经有一台运行中的服务器,想快速部署 JDK:

方法 A:使用默认仓库(推荐)

sudo apt update
sudo apt install -y openjdk-17-jdk

安装完成后,java 和 javac 命令通常会自动加入 PATH,无需手动配置环境变量。

方法 B:使用 SDKMAN!(适合多版本共存开发)

如果你需要在同一台机器上切换多个 JDK 版本(如测试 Java 8 和 Java 17),推荐使用 SDKMAN!:

# 安装 SDKMAN
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"

# 安装特定版本
sdk install java 17.0.9-tem

# 切换默认版本
sdk default java 17.0.9-tem

这种方式更灵活,适合开发者个人环境或 CI/CD 节点。


四、 常见坑与排查指南

1. “command not found: java” 怎么办?

大多数情况下,apt install openjdk-xx-jdk 会自动配置 /usr/bin/java 软链接。如果出现找不到命令,可能是:

  • PATH 未刷新:新开一个终端窗口,或执行 source ~/.bashrc。
  • 安装了 JRE 而非 JDK:确保安装的是 openjdk-xx-jdk,而不是 openjdk-xx-jre。
  • 替代机制问题:Debian/Ubuntu 使用 update-alternatives 管理多个 Java 实现。检查当前激活的是否是你安装的版本:
update-alternatives --list java
update-alternatives --display java

如果需要手动指定,可以运行:

sudo update-alternatives --config java

2. 如何设置 JAVA_HOME?

虽然现代应用(如 Spring Boot 内嵌 Tomcat)不依赖 JAVA_HOME,但某些老项目或工具链(如 Maven、Gradle、Ant)仍需要它。

编辑用户级配置文件:

nano ~/.bashrc

添加以下内容(以 OpenJDK 17 为例):

export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))
export PATH=$JAVA_HOME/bin:$PATH

然后生效:

source ~/.bashrc
echo $JAVA_HOME

技巧:$(dirname $(dirname $(readlink -f $(which java)))) 这个表达式能自动定位到 JDK 安装根目录,比硬编码路径更安全。

3. 内存不足导致安装失败?

小内存实例(如 512MB)在安装 JDK 时可能因编译头文件或缺乏 swap 而失败。解决方案:

  • 增加 Swap 分区:
    sudo fallocate -l 1G /swapfile
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    sudo swapon /swapfile
  • 或者先安装最小化运行时 openjdk-17-jre-headless,再按需扩展。

五、 总结建议

场景 推荐方案 理由
云服务器镜像预装 apt install openjdk-17-jdk-headless 体积小、无 GUI、易维护
开发机多版本管理 SDKMAN! 一键切换,不影响系统全局
生产环境容器化 Docker 基础镜像选用 eclipse-temurin 或 amazoncorretto 官方维护,持续安全更新

最后提醒:不要从第三方 PPA 或非官方源下载 JDK,优先使用 Ubuntu/Debian 官方源提供的 openjdk-* 包,这是最稳定、最安全的做法。