在部署 Java 应用时,JDK 是最基础的依赖。但很多人对 JDK 的认知停留在"装了就能跑 Java"的层面,不清楚它的内部组成、JDK 与 JRE 的区别,以及运维场景下需要关注哪些点。本文系统梳理 JDK 的核心概念和实践要点。
目录
[一、JDK 是什么](#一、JDK 是什么)
[2.1 编译器和运行时](#2.1 编译器和运行时)
[2.2 打包和文档工具](#2.2 打包和文档工具)
[2.3 调试和诊断工具](#2.3 调试和诊断工具)
[2.4 核心类库](#2.4 核心类库)
[三、JDK、JRE、JVM 的区别](#三、JDK、JRE、JVM 的区别)
[4.1 版本选择](#4.1 版本选择)
[4.2 发行版选择](#4.2 发行版选择)
[4.3 安装与环境变量](#4.3 安装与环境变量)
[4.4 常用诊断命令](#4.4 常用诊断命令)
[4.5 JVM 基础参数](#4.5 JVM 基础参数)
一、JDK 是什么
JDK(Java Development Kit)是 Java 开发工具包,包含了编译、运行、调试 Java 程序所需的全套工具和核心类库。简单来说,写 Java 和跑 Java 都依赖它。
JDK 不是一个单一的程序,而是一个工具集合。它的核心价值在于提供了从源码到运行的完整工具链,以及一套标准化的核心类库,使得 Java 程序可以"一次编写,到处运行"。
二、核心组成
2.1 编译器和运行时
|--------|-------------------------------------|
| 工具 | 作用 |
| javac | Java 编译器,将 .java 源码编译成 .class 字节码文件 |
| java | Java 启动器,启动 JVM 并加载运行字节码 |
| javap | 反编译工具,查看 .class 文件的字节码和结构 |
2.2 打包和文档工具
|---------|------------------------------------------|
| 工具 | 作用 |
| jar | 打包和解包 jar 文件,将多个 .class 和资源文件打包成一个可分发的单元 |
| javadoc | 根据源码中的注释生成 API 文档 |
| jlink | 模块化工具,创建自定义运行时镜像,减小部署体积 |
| jdeps | 依赖分析工具,分析类和模块的依赖关系 |
2.3 调试和诊断工具
这是运维人员最需要关注的部分,这些工具只有 JDK 才有,JRE 不包含:
|-----------|----------------------------------------|
| 工具 | 作用 |
| jdb | 命令行调试器 |
| jstack | 打印 Java 进程的线程栈,用于排查死锁、线程阻塞 |
| jmap | 导出堆转储文件,分析内存泄漏和对象分布 |
| jstat | 监控 JVM 统计信息,包括 GC、类加载、JIT 编译 |
| jcmd | 多功能诊断工具,JDK 8+ 推荐使用,可以替代 jstack、jmap 等 |
| jconsole | 图形化监控工具,查看内存、线程、GC 等实时信息 |
| jvisualvm | 更强大的图形化分析工具,支持性能分析和内存分析 |
2.4 核心类库
JDK 包含了 Java 标准库,从 Java 9 开始采用模块化设计(JPMS),核心类库被拆分为多个模块,其中最基础的是 java.base 模块,包含了 java.lang、java.util、java.io 等核心包。
三、JDK、JRE、JVM 的区别
这是 Java 领域最经典的概念区分,三者是包含关系:
JDK ⊃ JRE ⊃ JVM
开发工具 运行环境 虚拟机
(javac等) (类库) (执行字节码)
|--------|--------------------------|----------------------------------|--------------------|
| 名称 | 全称 | 能力 | 适用场景 |
| JVM | Java Virtual Machine | 只负责运行字节码,是一个抽象规范 | 内嵌在 JRE 中,不单独安装 |
| JRE | Java Runtime Environment | JVM + 核心类库,能运行 Java 程序 | 只运行应用、不需要开发和诊断的机器 |
| JDK | Java Development Kit | JRE + 开发工具 + 诊断工具,能开发和运行 Java 程序 | 开发机、构建机、需要排查问题的服务器 |
一个常见的误区是认为服务器上只需要 JRE。理论上没错,但实际运维中强烈建议安装 JDK,因为一旦应用出现性能问题或内存泄漏,没有 jstack、jmap 这些工具就无法排查。而且从 JDK 11 开始,Oracle 不再单独提供 JRE 下载,OpenJDK 的很多发行版也只提供 JDK,直接装 JDK 已经是标准做法。
四、运维实践要点
4.1 版本选择
Java 版本分为 LTS(长期支持)和非 LTS。生产环境必须使用 LTS 版本:
• Java 8:仍在大量老旧系统中使用
• Java 11:广泛使用的 LTS 版本
• Java 17:当前主流 LTS 版本
• Java 21:最新 LTS 版本,支持虚拟线程
非 LTS 版本(如 9、10、12、13、14、15、16、18、19、20)只提供 6 个月支持,不适合生产环境。
4.2 发行版选择
JDK 有多个发行版,功能基本一致,主要区别在于许可协议和支持周期:
|-----------------|----------------------------------|
| 发行版 | 说明 |
| Oracle JDK | Oracle 官方版本,商用需要付费 |
| OpenJDK | 开源参考实现,完全免费 |
| Eclipse Temurin | Eclipse 基金会维护的 OpenJDK 发行版,免费,推荐 |
| Amazon Corretto | AWS 维护的 OpenJDK 发行版,免费,长期支持 |
| Azul Zulu | Azul 系统维护的 OpenJDK 发行版 |
生产环境推荐使用 Eclipse Temurin 或 Amazon Corretto,免费且有长期安全更新。
4.3 安装与环境变量
安装 JDK 后需要配置 JAVA_HOME 和 PATH 环境变量:
# 查看 Java 版本
java -version
javac -version
# 查找 Java 安装路径
which java
readlink -f $(which java)
# 配置环境变量(以 /usr/lib/jvm/java-17-openjdk 为例)
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
export PATH=$JAVA_HOME/bin:$PATH
在多版本环境中,可以使用 update-alternatives 管理默认 Java 版本,或者用 jenv、sdkman 等工具切换版本。
4.4 常用诊断命令
# 查看 Java 进程
jps -l
# 查看线程栈(排查死锁、线程阻塞)
jstack <PID> > thread_dump.txt
# 导出堆转储(排查内存泄漏)
jmap -dump:format=b,file=heap.hprof <PID>
# 实时监控 GC
jstat -gcutil <PID> 1000
# 多功能诊断(推荐)
jcmd <PID> Thread.print
jcmd <PID> GC.heap_dump heap.hprof
jcmd <PID> VM.system_properties
4.5 JVM 基础参数
启动 Java 应用时,常见的 JVM 参数:
# 堆内存设置
-Xms2g -Xmx2g # 初始堆和最大堆,生产环境建议设为相同值避免动态调整
# GC 选择(Java 17 默认 G1,Java 21 默认 G1,可考虑 ZGC)
-XX:+UseG1GC
-XX:+UseZGC # 低延迟 GC,适合大堆和响应时间敏感的场景
# GC 日志
-Xlog:gc*:file=gc.log:time,uptime,level,tags
# OOM 时自动导出堆转储
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/log/heapdump/
五、总结
JDK 是 Java 生态的基石,它不仅仅是"运行 Java 的东西",而是一套包含编译、运行、调试、诊断、打包的完整工具链。理解 JDK、JRE、JVM 的区别,选择合适的版本和发行版,掌握 jstack、jmap、jstat 等诊断工具,是运维 Java 应用的基本功。
在生产环境中,建议始终安装完整的 JDK 而非 JRE,选择 LTS 版本和免费的 OpenJDK 发行版,并配置好 OOM 堆转储和 GC 日志,以便在出现问题时能够快速定位根因。