JDK 安装、环境变量与命令行工具 | JavaSE

JDK 安装、环境变量与命令行工具

一、学习目标

完成本章后,你应该能够:

  • 能够根据操作系统选择并安装正确的 JDK 21。
  • 能够解释 JDK 安装目录中 bin 等核心目录的作用。
  • 能够解释环境变量(Environment Variable)、PathJAVA_HOME 分别解决什么问题。
  • 能够在 Windows 中正确配置并检查 JAVA_HOMEPath
  • 能够使用 java -versionjavac -versionwhere java 等命令判断当前实际使用的 JDK。
  • 能够在完全不依赖 IntelliJ IDEA 的情况下,从零完成 Java 源文件的编写、编译和运行。
  • 能够分析 javajavac 版本不一致、命令找不到、文件名与类名不一致等典型环境问题。

二、核心知识

2.1 为什么学习 Java 的第一步是准备 JDK

上一章已经知道:

JDK(Java Development Kit)

是 Java 开发工具包。

如果只是理解 Java 概念,我们当然可以暂时不安装任何软件。

但一旦真正开始编写 Java 程序,就至少需要:

  • 编译 Java 源代码;
  • 启动 Java 程序;
  • 使用 Java 标准类库;
  • 使用 JDK 提供的开发工具。

这些能力都由 JDK 提供。

因此对于 Java 开发者来说:

安装 JDK,就是准备 Java 开发环境。

本教程统一以:

JDK 21

作为教学基线。

后面的所有代码、命令以及 API 说明,默认都以 JDK 21 为主要运行环境。


2.2 JDK 应该从哪里获得

JDK 并不只有一种发行方式。

在 Java 生态中,你可能见到:

  • Oracle JDK;
  • OpenJDK;
  • Eclipse Temurin;
  • Amazon Corretto;
  • Microsoft Build of OpenJDK;
  • 其他兼容 OpenJDK 的发行版。

它们都可能提供符合 Java 平台规范的 JDK。

但是为了让教学环境保持统一,本教程推荐初学阶段优先选择:

JDK 21 的稳定发行版本

并确保:

  • 版本明确;
  • 来源可靠;
  • 与操作系统匹配;
  • CPU 架构匹配。

例如 Windows 电脑常见:

Windows x64

Apple Silicon Mac 常见:

macOS AArch64 / ARM64

选择错误的操作系统或 CPU 架构,程序可能根本无法安装或运行。


2.3 JDK 安装以后在哪里

以 Windows 为例,Oracle JDK 21 默认安装位置通常类似:

C:\Program Files\Java\jdk-21

实际路径可能因为:

  • 安装方式;
  • JDK 小版本;
  • 自定义安装目录;
  • JDK 发行版;

而有所不同。

例如你也可以主动安装到:

D:\develop\java\jdk-21

重点不是背某一个固定目录,而是知道:

JDK Home 是哪一个目录。

例如:

D:\develop\java\jdk-21

就是一个可能的 JDK Home。

后面设置:

JAVA_HOME

时,通常就是让它指向这个目录。


2.4 JDK 的 bin 目录

打开 JDK 安装目录,可以看到多个子目录。

当前最需要认识的是:

bin

例如:

D:\develop\java\jdk-21\bin

bin 是 binary 的缩写。

这里存放大量可以直接执行的 JDK 工具。

例如:

java.exe
javac.exe
javadoc.exe
jar.exe
jshell.exe
jcmd.exe
jstack.exe
jmap.exe

当前最重要的是两个:

java
javac

2.5 javac 是什么

javac

Java Compiler

也就是 Java 编译器。

它的核心任务是:

Java 源代码
.java
   │
   │ javac
   ▼
Java 类文件
.class

例如:

javac HelloWorld.java

如果源代码合法,就可能生成:

HelloWorld.class

所以可以先记:

javac 负责“编译”。


2.6 java 是什么

java 是 Java 应用程序启动器。

经典使用方式:

java HelloWorld

它会启动 Java 运行环境,让 JVM 加载并执行对应的类。

所以可以先建立最重要的一组对应关系:

javac → 编译
java  → 运行

2.7 为什么在 JDK 的 bin 目录里可以执行 java

假设:

java.exe

真实位置是:

D:\develop\java\jdk-21\bin\java.exe

如果命令行当前就在:

D:\develop\java\jdk-21\bin

输入:

java -version

操作系统可以在当前目录中找到对应程序。

但是实际开发不可能每次使用 Java 命令之前都先进入:

D:\develop\java\jdk-21\bin

因此需要:

Path 环境变量。


2.8 什么是环境变量

环境变量(Environment Variable)可以理解为:

操作系统维护的一组“名称 → 值”的配置。

例如:

TEMP
Path
JAVA_HOME

不同环境变量承担不同作用。

某些是操作系统自己使用的。

某些是程序约定使用的。

Java 学习阶段最重要的是:

Path
JAVA_HOME

2.9 什么是 Path

Path 是操作系统用于搜索可执行程序的重要环境变量。

可以把它想象成一张:

“找程序的地址清单”

假设 Path 中包含:

C:\Windows\System32
D:\develop\java\jdk-21\bin

当你在任意目录输入:

javac

操作系统会依次到 Path 中记录的目录寻找:

javac.exe

如果找到了:

D:\develop\java\jdk-21\bin\javac.exe

就可以执行。

所以:

Path 解决的是“在什么目录下能够找到某个命令”。


2.10 为什么配置 JDK 的 Path

如果 JDK 的 bin 没有进入可搜索路径,那么:

java

或者:

javac

可能出现:

'javac' 不是内部或外部命令,
也不是可运行的程序或批处理文件。

这通常不是:

Java 代码写错了。

而是:

操作系统没有找到 javac.exe

如果 Path 中存在 JDK 的 bin

D:\develop\java\jdk-21\bin

就可以在:

C:\
D:\code
E:\JavaStudy

等任意目录直接输入:

javac

这就是 Path 的核心价值。


2.11 什么是 JAVA_HOME

JAVA_HOME 是 Java 生态中广泛使用的环境变量名称。

例如设置:

JAVA_HOME=D:\develop\java\jdk-21

它表达的意思可以理解为:

当前希望其他工具把这里当作 JDK 的主目录。

需要特别注意:

JAVA_HOME 不是 Java 语言的关键字,也不是运行任何 Java 程序都必须存在的 JVM 语法规则。

它是一种广泛采用的工具约定。

很多开发工具、构建工具、服务器或脚本会主动读取:

JAVA_HOME

来寻找 JDK。

因此配置它具有很高的工程价值。


2.12 JAVA_HOME 和 Path 有什么区别

假设:

JAVA_HOME=D:\develop\java\jdk-21

而 Path 中写:

%JAVA_HOME%\bin

则:

%JAVA_HOME%\bin

最终表示:

D:\develop\java\jdk-21\bin

两者职责不同:

| 环境变量 | 主要作用 | | ----------- | ------------------------------ | | JAVA_HOME | 告诉工具 JDK 主目录在哪里 | | Path | 告诉操作系统到哪些目录寻找命令 |

可以把它们理解为:

JAVA_HOME
   │
   └── JDK 在哪里?
           │
           ▼
D:\develop\java\jdk-21

Path
   │
   └── 命令去哪里找?
           │
           ▼
%JAVA_HOME%\bin

2.13 为什么推荐 Path 使用 %JAVA_HOME%\bin

当然可以直接写:

D:\develop\java\jdk-21\bin

但是更加灵活的配置方式是:

JAVA_HOME=D:\develop\java\jdk-21

Path:
%JAVA_HOME%\bin

以后如果 JDK 改成:

D:\develop\java\jdk-17

或者:

D:\develop\java\jdk-25

只需要修改:

JAVA_HOME

而不一定需要把所有引用 JDK Home 的地方全部重新修改。

这种思维本质上属于:

用一个稳定变量引用一个可能变化的真实路径。


三、使用方法

3.1 Windows 安装 JDK 21

以 Windows 为例。

基本流程:

下载 JDK
↓
运行安装程序
↓
确认安装目录
↓
检查 java / javac
↓
必要时配置 JAVA_HOME / Path
↓
再次验证

3.2 第一步:确认操作系统

先判断自己的系统。

Windows 中可以进入:

设置 → 系统 → 系统信息

重点确认:

  • 是否为 64 位系统;
  • CPU 架构。

绝大多数普通 Windows 电脑使用:

Windows x64

但不要完全依赖猜测。


3.3 第二步:安装 JDK 21

安装 JDK 21 时记录安装目录。

例如:

C:\Program Files\Java\jdk-21

或者你自己选择:

D:\develop\java\jdk-21

安装完成后,可以先进入:

jdk-21\bin

确认里面存在:

java.exe
javac.exe

3.4 第三步:验证 java

重新打开一个新的:

  • CMD;
  • PowerShell;
  • Windows Terminal;

输入:

java -version

正常情况下会看到包含:

21

的 Java 版本信息。

具体小版本号可能不同,例如:

21.0.x

不要死记完整输出。

判断重点是:

当前实际启动的 Java 是否属于 JDK 21。


3.5 第四步:验证 javac

继续输入:

javac -version

正常情况下会显示类似:

javac 21.0.x

重点检查:

java
javac

是否都能找到。


3.6 第五步:配置 JAVA_HOME

Windows 中可以搜索:

编辑系统环境变量

进入:

系统属性
→ 高级
→ 环境变量

新增:

变量名:
JAVA_HOME

变量值:
D:\develop\java\jdk-21

注意:

JAVA_HOME 一般应该指向:

JDK 根目录

而不是:

JDK\bin

也就是说推荐:

JAVA_HOME=D:\develop\java\jdk-21

而不是:

JAVA_HOME=D:\develop\java\jdk-21\bin

3.7 第六步:配置 Path

在 Path 中新增:

%JAVA_HOME%\bin

保存后关闭原来的终端。

重新打开一个新的 CMD,然后执行:

java -version
javac -version

因为已经打开的终端进程通常不会自动重新读取刚刚修改的全部环境变量。

所以:

修改环境变量后,新开终端再验证。


3.8 检查 JAVA_HOME

Windows CMD:

echo %JAVA_HOME%

理想输出类似:

D:\develop\java\jdk-21

PowerShell 中读取环境变量的写法不同:

$env:JAVA_HOME

理解:

CMD 与 PowerShell 是不同的命令行环境,环境变量语法不完全相同。


3.9 查看 Path

CMD:

echo %Path%

你会看到很多目录。

其中应该能够找到与 Java 相关的路径,例如:

D:\develop\java\jdk-21\bin

或者某些安装程序添加的 Java 命令路径。


3.10 到底执行的是哪个 java

这是排查 Java 环境问题时非常重要的一步。

Windows:

where java

可能得到:

D:\develop\java\jdk-21\bin\java.exe

也可能得到多个:

C:\Program Files\Common Files\Oracle\Java\javapath\java.exe
D:\develop\java\jdk-21\bin\java.exe

Path 中:

排在前面的匹配程序通常会优先被找到。

所以如果:

java -version

显示的并不是你想要的版本,就应该检查:

where java

3.11 查看 javac 的真实位置

同样:

where javac

然后比较:

where java
where javac

如果两个命令明显来自不同 JDK,环境就可能已经混乱。


3.12 完全不用 IDEA 编写第一个 Java 程序

现在正式通过命令行体验:

编写
→ 编译
→ 运行

创建一个目录:

D:\JavaStudy\hello

进入目录:

cd /d D:\JavaStudy\hello

新建:

HelloWorld.java

内容:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello Java!");
    }
}

3.13 编译程序

进入源文件目录后:

javac HelloWorld.java

如果没有错误,查看当前目录。

应该出现:

HelloWorld.java
HelloWorld.class

这里:

HelloWorld.java

是源代码。

HelloWorld.class

是编译后的类文件。


3.14 运行程序

执行:

java HelloWorld

注意:

不是:

java HelloWorld.class

经典 class 启动方式提供:

类名

而不是 class 文件名。

正常输出:

Hello Java!

这时整个链路已经真正跑通:

HelloWorld.java
        │
        │ javac
        ▼
HelloWorld.class
        │
        │ java
        ▼
       JVM
        │
        ▼
Hello Java!

3.15 修改代码以后为什么要重新 javac

假设源码改成:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello JDK 21!");
    }
}

如果只修改:

HelloWorld.java

但是没有重新:

javac HelloWorld.java

那么原来的:

HelloWorld.class

并不会自动因为文本文件改变而同步更新。

因此经典命令行流程必须:

修改源码
↓
保存
↓
重新 javac
↓
生成新 class
↓
java 执行

这也是理解 IDE 自动构建行为的重要基础。


3.16 Java 21 也支持直接运行单个源文件

除了经典方式:

javac HelloWorld.java
java HelloWorld

现代 Java 还支持单源文件启动模式。

例如:

java HelloWorld.java

Java 启动器可以在内存中完成必要的编译并执行源文件。

但是本教程仍然要求你先真正掌握:

javac
+
java

因为它能够清晰展示:

源码
→ 编译
→ class
→ 运行

这条 Java 基本执行链路。


四、原理与进阶

4.1 输入 java 后操作系统到底做了什么

假设你输入:

java -version

可以简化理解为:

Shell 接收到 java
        │
        ▼
当前目录 / Path 搜索
        │
        ▼
找到 java.exe
        │
        ▼
启动该程序
        │
        ▼
java.exe 启动对应 JVM

所以:

java 命令找不到,本质首先是操作系统的程序查找问题。

不是 Java 语法问题。


4.2 为什么会出现多个 Java

一台电脑完全可能安装:

JDK 8
JDK 17
JDK 21
JDK 25

例如:

C:\Java\jdk8
C:\Java\jdk17
C:\Java\jdk21

如果 Path 配置混乱,就可能出现:

java → JDK 8
javac → JDK 21
IDEA → JDK 17
Maven → JDK 21

此时你会产生一种错觉:

“我电脑明明安装了 JDK 21,为什么程序不是 21?”

因为:

安装了什么 ≠ 当前真正使用什么。

真正应该查:

java -version
javac -version
where java
where javac

4.3 Path 顺序为什么重要

假设 Path 中顺序是:

C:\Java\jdk8\bin

D:\Java\jdk21\bin

输入:

java

操作系统先在第一个目录找到:

java.exe

通常就不会继续选择后面的 JDK 21。

于是:

java -version

可能显示 Java 8。

所以环境配置不仅是:

“有没有 Java 路径”。

还要检查:

“哪个 Java 路径排在前面”。


4.4 JAVA_HOME 不决定 java 命令一定使用哪个 JDK

这是非常重要的误区。

假设:

JAVA_HOME=D:\Java\jdk21

但是 Path 最前面却是:

C:\Java\jdk8\bin

那么在普通命令行输入:

java

操作系统仍然可能首先运行:

C:\Java\jdk8\bin\java.exe

因此:

JAVA_HOME

和:

Path

必须分开理解。

最常见的稳定配置:

JAVA_HOME=D:\Java\jdk21

Path:

%JAVA_HOME%\bin

4.5 用户变量与系统变量

Windows 环境变量通常可以分为:

  • 用户变量;
  • 系统变量。

用户变量主要影响:

当前用户。

系统变量则通常影响:

整台系统中的用户和程序环境。

学习阶段不需要死记复杂优先级规则。

需要掌握的是:

  • 知道自己把 JAVA_HOME 配在哪里;
  • 知道 Path 中是否存在 Java;
  • 会使用实际命令验证结果。

不要只看 GUI 配置界面“感觉配好了”。

最终判断依据应该是:

java -version
javac -version
where java
where javac

4.6 不建议随意设置全局 CLASSPATH

旧 Java 教程中经常把:

CLASSPATH

和:

JAVA_HOME
Path

一起要求初学者全局配置。

现代 Java 基础学习中通常:

不需要为了写 HelloWorld 主动设置全局 CLASSPATH。

javacjava 都提供:

--class-path
-cp

等方式显式指定类路径。

错误的全局 CLASSPATH 反而可能制造非常隐蔽的类加载问题。

所以当前阶段:

JAVA_HOME
Path

足够。

类路径会在后续真正需要的时候再系统理解。


五、实践应用

5.1 场景:java -version 是 21,javac -version 是 17

先执行:

where java
where javac

可能发现:

java.exe
→ D:\Java\jdk21\bin

javac.exe
→ D:\Java\jdk17\bin

说明 Path 中不同 Java 路径产生了冲突。

处理思路:

确认目标 JDK
↓
确认 JAVA_HOME
↓
整理 Path
↓
移除或下移错误路径
↓
新开终端
↓
重新验证

5.2 场景:IDEA 能运行,CMD 不能运行

可能出现:

IDEA:能运行 Java

CMD:
'javac' 不是内部或外部命令

原因可能是:

IDEA 自己配置了 Project SDK,所以它知道 JDK 在哪里。

但是 Windows Path 没配置,因此普通命令行不知道:

javac.exe

在哪里。

这正说明:

IDE 的 Java 环境和操作系统命令行环境并不完全是一回事。


5.3 场景:换 JDK 后版本没有变化

修改了环境变量以后:

java -version

还是旧版本。

第一步不要急着重装。

先:

关闭旧终端
→ 新开 CMD

因为已经运行的终端进程可能仍然保留旧环境。

然后执行:

where java
java -version

继续判断。


5.4 场景:项目要求 JDK 21,但电脑有多个 JDK

不要删除所有其他 JDK。

真实开发环境中同时存在多个版本是正常的。

关键是学会:

  • 系统默认 JDK 是谁;
  • JAVA_HOME 指向谁;
  • IDE 项目 JDK 是谁;
  • 构建工具实际使用谁。

成熟的开发者不是:

“电脑里只有一个 JDK,所以永远不会乱。”

而是:

“即使存在多个 JDK,我也知道每个工具真正用了哪一个。”


六、常见问题

6.1 java 能用,为什么 javac 不能用?

可能存在:

  • Path 只指向某个运行时环境;
  • 多版本 Java 冲突;
  • javac 路径没有进入 Path;
  • 安装不完整。

先执行:

where java
where javac

再判断。


6.2 为什么 JAVA_HOME 不应该直接指向 bin

推荐:

JAVA_HOME=D:\develop\java\jdk-21

因为它表达的是:

JDK Home。

Path 再引用:

%JAVA_HOME%\bin

职责更加清晰。


6.3 修改 Path 后为什么还是找不到 Java?

可能因为:

  • 旧终端没有关闭;
  • 路径拼写错误;
  • JAVA_HOME 写错;
  • %JAVA_HOME%\bin 实际不存在;
  • Path 配置没有保存;
  • 多个路径发生冲突。

排查:

echo %JAVA_HOME%
where java
where javac
java -version
javac -version

6.4 为什么文件名必须和 public class 类名一致?

如果代码:

public class HelloWorld {
}

则源文件应该叫:

HelloWorld.java

Java 编译器要求:

顶层 public 类的名称与源文件名称匹配。

如果文件叫:

Test.java

却写:

public class HelloWorld

编译器会报告错误。


6.5 为什么 java HelloWorld.class 不对?

经典 class 启动模式中:

java HelloWorld

提供的是:

主类名称。

而不是:

class 文件名。


6.6 javac 没有任何输出,是不是失败了?

不一定。

很多命令遵循:

成功时保持安静,失败时输出错误。

执行:

javac HelloWorld.java

没有错误输出,并且产生:

HelloWorld.class

通常就说明编译成功。


6.7 为什么现在可以 java HelloWorld.java,还要学 javac?

因为:

java HelloWorld.java

属于现代 Java 提供的单源文件启动方式。

但是:

javac HelloWorld.java
java HelloWorld

能让你真正观察:

源代码
→ class
→ JVM

后面的:

  • 多文件程序;
  • 编译输出;
  • classpath;
  • IDE 构建;

都建立在这个模型之上。


6.8 JDK 安装程序会不会自动把 Java 配进 Path?

不同:

  • JDK 发行版;
  • 安装器;
  • 操作系统;
  • 安装方式;

行为可能不同。

某些安装程序会主动提供可以从命令行访问 Java 的路径。

但是不要只相信:

“它应该自动配好了。”

真正可靠的方法永远是:

java -version
javac -version
where java
where javac

让实际结果说话。


七、练习与验收

7.1 知识问答

  1. 为什么开发 Java 程序需要 JDK?
  2. JDK 安装目录中的 bin 主要保存什么?
  3. javajavac 分别解决什么问题?
  4. 什么是环境变量?
  5. Path 环境变量的核心作用是什么?
  6. JAVA_HOME 解决什么问题?
  7. JAVA_HOME 与 Path 有什么区别?
  8. 为什么推荐在 Path 中使用 %JAVA_HOME%\bin
  9. 为什么“已经安装 JDK 21”不代表 java 命令当前使用的一定是 21?
  10. Windows 中如何判断 java.exe 实际来自哪个目录?
  11. 为什么修改环境变量后通常需要重新打开终端?
  12. 为什么不推荐初学阶段随意配置全局 CLASSPATH

7.2 代码阅读

阅读:

public class HelloJava {
    public static void main(String[] args) {
        System.out.println("Hello Java");
    }
}

假设源文件:

HelloJava.java

回答:

  1. 使用什么命令编译?
  2. 编译成功后通常产生什么文件?
  3. 使用什么命令运行?
  4. 如果修改源码但不重新编译,旧 .class 是否会自动改变?
  5. 如果文件名改为 Test.java,但代码仍然是 public class HelloJava,可能发生什么?

7.3 手写代码

不使用 IDEA。

完成:

  1. 创建:
HelloWorld.java
  1. 手写标准 Java 程序。
  2. 输出:
The harder you try, the luckier you get
  1. 使用:
javac HelloWorld.java

完成编译。

  1. 找到:
HelloWorld.class
  1. 使用:
java HelloWorld

运行。

  1. 写出每一步对应:
源码
编译器
字节码
JVM

中的哪一个阶段。


7.4 Debug

Debug 1:找不到 javac

终端显示:

'javac' 不是内部或外部命令

请设计完整排查流程。

至少检查:

JDK 是否安装
JAVA_HOME
Path
where javac
javac -version

Debug 2:版本不一致

java -version
→ 21

javac -version
→ 17

要求:

  1. 推测最可能的问题。
  2. 使用命令找出两个程序的真实路径。
  3. 说明应该修改 JAVA_HOME 还是 Path,或者二者都需要检查。
  4. 修复以后重新验证。

Debug 3:类名与文件名不一致

文件:

Test.java

代码:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello");
    }
}

判断:

  • 问题发生在编译期还是运行期?
  • 为什么?
  • 有哪两种最直接的修复方法?

7.5 综合训练

假设电脑中存在:

C:\Java\jdk17
D:\Java\jdk21

当前:

JAVA_HOME=D:\Java\jdk21

但是:

java -version

仍然显示:

17

请完成一次完整诊断。

要求:

  1. 查看 JAVA_HOME
  2. 查看 Path
  3. 使用 where java
  4. 判断优先级问题;
  5. 修改环境变量;
  6. 新开终端;
  7. 验证 java
  8. 验证 javac
  9. 最后从零编译和运行一个 Java 文件。

整个过程中,不允许简单使用:

“重装 JDK”

作为第一解决方案。


7.6 本章验收

在不查看资料的情况下:

  • [ ] 能说明 JDK 安装以后最重要的目录。
  • [ ] 能解释 JAVA_HOME 和 Path 的区别。
  • [ ] 能独立完成 Windows JDK 21 环境配置。
  • [ ] 能使用 java -versionjavac -version 验证版本。
  • [ ] 能使用 where javawhere javac 定位程序。
  • [ ] 能在完全不使用 IDEA 的情况下创建、编译并运行 Java 程序。
  • [ ] 能解释 .java.class 的关系。
  • [ ] 能解决 java / javac 版本不一致问题。
  • [ ] 能解决“命令找不到”问题。
  • [ ] 能解释为什么安装成功不等于环境配置一定正确。