
Java JDK 是什么?从安装到运行第一个程序
想学习 Java、构建后端服务,或者运行需要 Java 环境的软件,常会遇到“安装 JDK”这一步。JDK 不只是一个用来启动 Java 程序的文件包,它还包含编译器、调试器和其他开发工具。理解 JDK 与运行时的关系,选对版本并配置好命令行环境,后续编译和运行程序就会清楚很多。
本文从 JDK 的组成、适用场景和边界讲起,分别介绍 Windows、macOS 和 Linux 上的安装与验证,再用一个完整示例编译、运行 Java 程序。示例以命令行操作为主,不依赖 IDE。
一、JDK 是什么
JDK 是 Java Development Kit 的缩写,通常译为 Java 开发工具包。它提供开发 Java 程序所需的工具和运行组件。常见组成包括:
javac:Java 编译器,将 Java 源代码编译为字节码。java:Java 启动器,用于启动 Java 应用。jar:用于创建和处理 JAR 文件。javadoc:从源代码注释生成 API 文档。jshell:交互式 Java 命令行工具,适合试验表达式和小段代码。- 运行 Java 程序所需的组件,例如 Java 虚拟机(JVM)和标准类库。
JDK 是开发套件,不等同于 Java 语言本身,也不等同于 IDE。Java 是语言及其平台规范的一部分;Eclipse、IntelliJ IDEA、Visual Studio Code 等是开发工具,它们可以调用本机安装的 JDK,也可能通过扩展或构建工具配置使用其他 JDK。
JDK、JRE 和 JVM 有什么区别
- JVM 是执行 Java 字节码的虚拟机。它负责加载类、执行字节码,并进行内存管理等工作。
- JRE 是 Java 运行环境这一概念,通常指运行 Java 程序需要的 JVM 和相关类库。不同发行版、不同年代对 JRE 的打包方式可能不同。
- JDK 在运行环境的基础上提供编译和开发工具,因此既可用于开发,也可用于运行程序。
需要注意,不能假定每个 JDK 安装包里都带有一个独立、可单独安装的“JRE”。从模块化的 JDK 9 开始,Oracle JDK 不再像早期版本那样提供传统的独立 JRE 安装包;其他发行版和版本的分发方式也可能不同。通常开发时安装 JDK 即可。生产环境若需要更小的运行镜像,可以使用相应工具定制运行时,但必须确认应用需要的模块、服务及本地依赖都已包含。
二、JDK 适合用在哪些场景
Java 被用于多种软件开发场景。安装 JDK 后,可以进行以下工作:
- 后端服务:开发 Web API、企业应用、任务处理服务等,常与 Spring 等框架和 Maven、Gradle 等构建工具配合。
- 命令行工具:编写跨平台的数据处理、自动化和运维辅助程序。
- 桌面应用:开发 Java 桌面软件。是否适合具体项目,还要结合界面框架、部署方式和目标平台评估。
- 大数据与基础设施软件:不少相关框架和服务提供 Java API,或基于 Java 运行。
- 学习与实验:用
javac、java和jshell理解语言、类库和虚拟机的基本机制。
JDK 本身不会替你解决应用架构、依赖管理、部署或监控问题。开发大型项目时,通常还要使用构建工具、测试框架、版本控制系统和合适的 IDE。也要留意目标平台:应用虽然编译成字节码,但依赖本地动态库、操作系统特性或特定 JDK 模块时,并不一定能不经调整地跨平台运行。
三、选择 JDK 版本与发行版
Java 有多个版本和多个 JDK 发行版。Oracle JDK、Eclipse Temurin、Amazon Corretto、Microsoft Build of OpenJDK 等都是常见选择;它们在许可、支持周期、更新渠道和服务承诺上可能不同。选择前应查看发行版官网的许可说明、支持政策以及目标项目要求。
对于新项目,优先查看组织或框架明确支持的 Java 版本。长期支持(LTS)版本适合需要较长维护周期的项目,但“LTS”一词具体对应的支持服务和期限,取决于发行版及其政策,不意味着所有厂商都以相同方式、免费提供同样时长的更新。
项目可能要求某个特定的 Java 版本。安装了更高版本的 JDK,并不能自动保证项目兼容:代码可能使用了新版本才有的 API,构建插件也可能不支持新版本。反过来,编译器可通过 --release 指定目标 Java 平台,但这不等于能把任意新版本依赖变成旧版本兼容,也不能消除第三方库的版本限制。实际项目应以构建配置、依赖要求和部署环境为准。
四、安装 JDK
先从发行版的官方网站或可信的软件包仓库选择适合操作系统和处理器架构的安装包。常见架构名称包括 x64(也称 x86_64)和 ARM64(也称 AArch64)。下载前确认操作系统版本、处理器架构和许可要求。安装过程中如果系统询问是否设置环境变量,可按安装包说明操作;不同发行版的安装器选项并不完全相同。
Windows
- 下载与 Windows 和处理器架构匹配的 JDK 安装包,按提示安装。记录安装目录,例如
C:\Program Files\Eclipse Adoptium\jdk-21.0.x.x-hotspot;实际目录以机器上的版本为准。 - 打开新的 PowerShell 窗口,执行
java -version和javac -version,检查系统是否能找到命令。 - 如果提示找不到命令,在系统的环境变量设置中将 JDK 的
bin目录加入Path。也可以设置JAVA_HOME指向 JDK 根目录,再把%JAVA_HOME%\bin加入Path。
JAVA_HOME 是许多构建工具和开发软件会读取的环境变量,但 Java 启动器本身并不要求必须设置它。设置时应指向 JDK 根目录,而不是 bin 子目录。修改环境变量后要新开终端,让新进程读取更新后的设置。
PowerShell 的临时设置只对当前会话有效,可用于验证路径是否正确:
$env:JAVA_HOME = "C:\Program Files\Eclipse Adoptium\jdk-21.0.x.x-hotspot"
$env:Path = "$env:JAVA_HOME\bin;$env:Path"
java -version
javac -version
这段命令中的目录应替换为本机真实的 JDK 安装目录。需要长期使用时,应在 Windows 的系统环境变量设置中保存,而不是每次手动执行。
macOS
可以使用发行版提供的 macOS 安装包,或采用经确认的包管理方式安装。Apple 芯片设备和 Intel 设备要选择相应架构的版本。安装后打开终端检查:
java -version
javac -version
macOS 通常可以通过 /usr/libexec/java_home 查询已注册的 JDK,例如:
/usr/libexec/java_home -V
若需要为当前终端会话设置 JAVA_HOME,可以执行:
export JAVA_HOME=$(/usr/libexec/java_home)
export PATH="$JAVA_HOME/bin:$PATH"
若要让设置在后续终端中继续生效,可将相应设置加入当前 Shell 使用的配置文件,例如 zsh 通常使用 ~/.zshrc。编辑后重新打开终端,或按需加载配置文件。不要把示例路径或命令不加判断地复制到所有 macOS 环境中;安装方式和 Shell 配置可能不同。
Linux
可以使用发行版仓库中的 OpenJDK 软件包,也可以使用 JDK 发行版提供的安装包。包名随 Linux 发行版变化。例如,在基于 Debian 的系统上,软件包可能名为 openjdk-21-jdk;在其他发行版上名称和安装命令可能不同。应以当前发行版的软件包仓库说明为准。
安装后打开新终端并检查:
java -version
javac -version
如果机器上安装了多个 JDK,系统可能通过发行版的选择机制决定默认版本,也可能先找到 PATH 中排在前面的版本。此时除了确认“装了哪个版本”,还要确认“当前命令实际运行的是哪个版本”。
五、运行第一个 Java 程序
下面编写一个无需外部依赖的程序,读取命令行参数,并打印问候语。请创建文件 HelloJava.java,内容如下:
public class HelloJava {
public static void main(String[] args) {
String name = args.length > 0 ? args[0] : "世界";
System.out.println("你好," + name + "!");
}
}
注意:文件名必须是 HelloJava.java,并与公开类名 HelloJava 匹配。Java 区分大小写,类名和文件名大小写不一致时可能无法编译,尤其是在区分大小写的文件系统中。
方式一:先编译,再运行
在保存源代码的目录中打开终端,检查当前目录,并执行编译:
javac HelloJava.java
如果成功,目录中会生成 HelloJava.class。这个文件包含 Java 字节码,不是可直接作为操作系统程序运行的原生可执行文件。使用 Java 启动器运行类时,写类名而不是带扩展名的文件名:
java HelloJava
预期输出为:
你好,世界!
命令行参数放在类名之后。以下命令会把 张三 作为第一个参数传给程序:
java HelloJava 张三
输出为:
你好,张三!
含空格的参数应使用引号括起来,例如:
java HelloJava "Ada Lovelace"
引号由 Shell 用来把内容组合成一个参数,通常不会作为参数内容传入 Java 程序。不同命令行环境对引号和转义字符的处理可能不同;如需逐个读取参数,可在程序中遍历 args 数组。
方式二:直接运行源文件
较新的 Java 启动器支持直接运行单个源文件,不必先手动执行 javac:
java HelloJava.java
源文件启动方式适合小型示例和脚本式实验。它不代表大型项目不再需要编译和构建工具;复杂项目仍要处理多个源文件、依赖、资源文件、测试和打包。该功能从 Java 11 开始提供,若命令报错,先确认运行时版本。
六、理解 Java 命令的参数
java 命令既接受 JVM 或启动器选项,也接受要运行的主类、JAR 文件或源文件及其参数。选项要放在相应运行目标之前;运行目标之后的内容通常作为程序参数传递。例如:
java -cp out HelloJava 张三
这里 -cp out 指定类路径目录,HelloJava 是主类名,张三 是应用参数。-cp(也可写作 -classpath)用于告诉启动器到哪里查找类和资源;具体路径分隔符取决于操作系统:Windows 通常用分号,macOS 和 Linux 通常用冒号。
运行打包好的 JAR 时,常见形式是:
java -jar app.jar
此时 JAR 中必须有可用的入口配置,即清单文件中的 Main-Class。使用 -jar 模式时,应按启动器规则在 JAR 文件之后提供应用参数。若直接运行 JAR 报“没有主清单属性”一类错误,通常表示这个 JAR 没有配置可执行入口,或者它本来就不是可执行 JAR。
选项是否可用、拼写方式和行为可能随 JDK 版本而变化。需要查看当前环境的选项时,可执行:
java --help
javac --help
不要将内存参数当成可以无限扩容的开关。例如,HotSpot 常见参数 -Xms 和 -Xmx 分别用于设置堆的初始大小和最大大小,但受可用内存、操作系统、容器配置、JDK 实现和其他 JVM 开销影响。堆并不等于进程全部内存,线程栈、元空间、代码缓存和本地内存也会占用资源。设置过大可能导致内存不足;设置过小则可能导致频繁垃圾回收或程序失败。参数格式和单位应以目标 JDK 文档为准。
命令行长度也不是无限的。操作系统和终端对一次调用可传递的参数总长度有各自限制,限制会随平台及调用方式变化,不存在一个适用于所有系统和 Java 程序的统一数值。大量文件路径或参数应考虑使用构建工具、类路径通配配置、参数文件(在相应工具支持时)或由程序读取文件,而不是假设超长命令在所有环境都能工作。
七、JDK 与安全:能做什么,不能做什么
JDK 提供实现应用安全功能所需的 API 和工具,但安装 JDK 本身不会自动让应用安全。Java 类库提供加密、证书、密钥库、TLS 等相关能力;其具体支持范围和配置方式取决于 JDK 版本及发行版。正确使用这些 API,仍需要遵守密钥管理、证书验证、算法选择和协议配置要求。
例如,程序通过 HTTPS 访问服务时,应正确验证对端证书和主机名。为了让连接“先跑起来”而关闭证书校验,会使连接失去重要的身份验证保护,可能受到中间人攻击。不要在生产环境中忽略证书错误,也不要把密码、私钥或访问令牌明文写入源代码仓库。
Java 也不是天然的安全沙箱。不要把运行未知来源的 JAR 当作安全操作:它可以尝试读写当前用户有权限访问的文件、发起网络连接、消耗大量资源,或调用本地代码。应只运行可信的软件;如必须运行不可信代码,应使用操作系统权限隔离、容器或虚拟机等边界,并设置资源和网络策略。容器本身也需要合理配置,不能仅凭“放进容器”就认定风险已消除。
历史上的 Java 安全模型曾使用 SecurityManager 做部分权限检查,但它不是通用的恶意代码隔离方案。该机制在较新版本中已被弃用,并在 Java 24 起按 JEP 486 永久禁用;依赖它进行安全边界控制的旧应用,需要依据目标版本评估并迁移。不能把旧教程中的策略文件或 -Djava.security.manager 用法当成适用于所有现代 JDK 的安全方案。
安全更新同样重要。生产环境应跟踪所选发行版的更新渠道,及时评估并安装安全修复;升级前要验证应用、框架、构建工具和部署平台的兼容性。是否采用某个版本,应结合实际支持政策,而非仅依据版本号大小判断。
八、常见错误与排查方式
1. 提示找不到 java 或 javac
可能是 JDK 没有安装,或 JDK 的 bin 目录不在 PATH 中。也可能只安装了不含编译器的运行环境。先在新终端中分别执行 java -version 和 javac -version。如果前者成功、后者失败,检查是否安装了 JDK,以及当前找到的目录是否真的是 JDK,而不是另一个运行环境。
2. 实际使用的版本与预期不同
机器上可能存在多个 JDK,或者 IDE、构建工具单独指定了版本。可检查操作系统实际解析到的命令位置:Windows 使用 where java,macOS 和 Linux 使用 which java;还可以查看 JAVA_HOME,并在构建工具或 IDE 设置中检查项目使用的 JDK。终端里的 Java 版本正确,不代表所有 IDE 和构建任务也使用同一版本。
3. 提示找不到类或主类
首先确认已在正确目录运行命令,编译是否成功,类名大小写是否正确。如果 .class 文件不在当前类路径中,使用 -cp 指定包含该文件的目录。运行普通类时不要写 java HelloJava.class;应写 java HelloJava。
4. 找不到符号或 API 不存在
这通常表示代码拼写、导入或依赖有问题,也可能是编译时 JDK 版本低于代码使用的 API 所属版本。确认实际执行的 javac 版本,并检查项目依赖。不要只通过修改 IDE 的语言级别来判断兼容性;构建工具和部署运行时也必须匹配。
5. 类版本不兼容
如果程序用较新的 JDK 编译,却在较旧的运行时上启动,可能出现类版本不兼容错误。要么升级运行时,要么使用较旧版本支持的 API 和编译配置重新构建,并确保依赖也兼容。javac --release 目标版本 可用于约束目标平台 API 和生成的类文件版本,但不能保证外部库、反射行为或运行环境的所有部分都兼容。
6. 中文显示乱码
乱码可能来自源文件编码、编译器输入编码、终端编码或字体配置。确认源文件以合适的字符编码保存,并让编辑器、构建工具和终端使用一致的编码。较新版本的 Java 默认编码行为与早期版本有所变化;遇到跨系统问题时,不要猜测默认值,应检查实际文件和进程配置,必要时明确设置编译或应用编码。
7. 安装或更新后命令仍指向旧版本
修改 PATH 后,已经打开的终端通常不会自动读取新设置。先打开新的终端,再检查命令实际路径和版本。若多个目录都包含 Java,调整路径顺序或使用系统提供的版本切换机制,并确认 IDE、服务管理器和自动化任务没有单独配置旧路径。
九、什么时候还需要构建工具
上面的例子只包含一个源文件,直接使用 javac 已经足够。项目开始依赖第三方库、包含多个源代码目录或需要自动化测试时,通常应引入 Maven 或 Gradle 等构建工具。构建工具可以声明依赖、编译选项和测试任务,降低手动维护类路径的负担。
例如,一个团队项目可以通过构建配置记录所需 Java 版本,并让开发机与持续集成环境使用一致的编译规则。不过,构建工具本身也有版本兼容要求:需要检查它支持的 JDK 范围、插件版本以及项目使用的框架约束。开发时使用的 JDK、编译目标版本和生产运行时是相互关联但不同的配置,不应混为一谈。
十、快速检查清单
- 确认目标项目要求的 Java 版本、发行版和许可条件。
- 为操作系统与处理器架构选择匹配的 JDK。
- 在新终端中确认
java -version和javac -version。 - 需要时设置
JAVA_HOME,并确认PATH中优先找到正确的 JDK。 - 保存
HelloJava.java,使用javac HelloJava.java编译,再用java HelloJava运行。 - 运行不可信程序时,不要把 JDK 或旧式沙箱机制当作隔离边界。
理解 JDK 的关键,是区分开发工具、运行环境、字节码和具体 JDK 实现:编译器负责把源代码转换为字节码,启动器和虚拟机负责加载并执行程序,而开发、打包和安全策略还需要结合项目与操作系统环境。掌握版本选择、命令行配置和基本排查方法后,就可以从一个小程序开始,再逐步扩展到完整的 Java 项目。









