"李眉把装机文档往群里一扔:'JDK 8安装步骤写好了,Windows的,每一步都截了图。'白歌扫了一眼:'环境变量那块再写细点,JAVA_HOME、Path、CLASSPATH三个都要讲清楚。'小崔在下面回复:'李姐威武!终于不用每次配环境都百度了。'"
JDK安装与配置
本章定位
手把手在Windows上安装JDK 8,深入理解JAVA_HOME、Path、CLASSPATH环境变量的作用和原理,掌握java/javac -version验证安装的正确姿势。这是编程的"装机第一步"。
JDK vs JRE vs JVM 关系深度剖析
包含关系图
职责划分表
| 组件 | 英文全称 | 一句话职责 | 包含什么 | 谁需要 |
|---|---|---|---|---|
| JDK | Java Development Kit | 开发和运行Java程序 | JRE + javac + jar + javadoc + javap | 开发者 |
| JRE | Java Runtime Environment | 仅运行Java程序 | JVM + rt.jar核心类库 | 最终用户 |
| JVM | Java Virtual Machine | 执行字节码 | 类加载器 + JIT编译器 + GC + 执行引擎 | 任何运行Java的地方 |
三者关系的经典类比
如果把Java程序比作一辆汽车:
JDK = 汽车制造工厂(包含生产线 + 测试跑道 + 所有工具)
JRE = 公路系统(包含道路 + 交通规则)
JVM = 发动机(真正让车跑起来的核心)
JDK 8 下载与安装
下载Oracle JDK 8
版本说明:本教程使用 Oracle JDK 8u202(JDK 8的最后一个免费商用版本)或 OpenJDK 8(完全开源)。两者API完全一致,企业环境中根据授权策略选择。
下载地址:
- Oracle JDK 8(需注册Oracle账号):https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html
- OpenJDK 8(可选的免费替代):https://adoptium.net/download/
Windows安装步骤
- 双击安装包
jdk-8u202-windows-x64.exe - 安装目录选择
C:\Program Files\Java\jdk1.8.0_202\(建议保持默认) - 等待安装完成。注意:安装过程中会弹出JRE安装窗口,这是独立JRE(可取消,因为JDK已自带JRE)。
- 安装完成后,目录结构如下:
C:\Program Files\Java\jdk1.8.0_202\
├── bin/ ← 可执行文件(javac.exe, java.exe, javap.exe...)
├── jre/ ← JDK自带的JRE
│ ├── bin/
│ └── lib/
│ └── rt.jar ← 核心类库(运行时)
├── lib/ ← JDK开发工具库
│ └── tools.jar ← javac等编译器核心代码
├── include/ ← JNI本地调用头文件
└── src.zip ← JDK核心类库源码(学习JDK源码从这里开始)
环境变量配置:JAVA_HOME、Path、CLASSPATH
环境变量是操作系统级别的全局配置,告诉命令行"javac在哪"、"运行时类库在哪"。这是初学者最容易配错的地方。
配置步骤(Windows 10/11)
步骤一:打开环境变量配置
右键"此电脑" → 属性 → 高级系统设置 → 环境变量。分为用户变量(仅当前用户生效)和系统变量(所有用户生效)。建议配置到系统变量。
步骤二:配置JAVA_HOME
| 变量名 | 变量值 |
|---|---|
JAVA_HOME | C:\Program Files\Java\jdk1.8.0_202 |
说明:JAVA_HOME 指向JDK安装根目录(不是bin目录)。
用途:许多Java工具(Tomcat、Maven、Gradle、Eclipse/IDEA)都依赖JAVA_HOME定位JDK。
步骤三:配置Path
在系统变量Path中新增一条:
%JAVA_HOME%\bin
注意:放在Path的靠前位置,避免被其他程序的java.exe覆盖(如某些软件自带的旧版Java)。
步骤四:配置CLASSPATH(可选)
| 变量名 | 变量值 |
|---|---|
CLASSPATH | .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar |
说明:
. → 当前目录(重要!不加这个可能找不到当前目录下的.class)
dt.jar → Java设计时API(Swing等)
tools.jar → javac等编译工具的核心代码
JDK 8中仍需配置,JDK 9+ 因模块化已不需要tools.jar和dt.jar。
实际上,JDK 8 日常开发中,只要确保 "." 在CLASSPATH中即可,
java命令默认已自动包含rt.jar,无需手动指定。
最佳实践:JDK 8通常不需要手动设置CLASSPATH环境变量。当你使用
java -cp或java -classpath参数时,命令行参数会覆盖CLASSPATH环境变量。对初学者而言,不设CLASSPATH比设置错误要好。
验证安装
验证清单
打开新的命令提示符窗口(Win+R → cmd),依次执行以下命令:
| 命令 | 预期结果 | 验证目的 |
|---|---|---|
java -version | 显示JDK版本信息 | 验证java命令可用 |
javac -version | 显示javac版本信息 | 验证javac命令可用 |
echo %JAVA_HOME% | 显示JDK安装路径 | 验证JAVA_HOME配置正确 |
echo %Path% | 包含JDK/bin路径 | 验证Path配置正确 |
正确输出示例
C:\Users\xiaocui> java -version
java version "1.8.0_202"
Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)
C:\Users\xiaocui> javac -version
javac 1.8.0_202
C:\Users\xiaocui> echo %JAVA_HOME%
C:\Program Files\Java\jdk1.8.0_202
代码示例:验证JDK环境配置的Java程序
白歌给小崔写了一个"JDK环境自检"程序,确保团队每个人的开发环境一致:
/**
* JDKEnvChecker.java
* 用途:验证JDK 8环境配置是否正确
* 场景:飞翔科技新人入职,白歌要求新员工运行此程序确认环境就绪
*/
public class JDKEnvChecker {
public static void main(String[] args) {
String companyName = "广州飞翔科技";
String checkerVersion = "v1.0";
boolean allPassed = true;
System.out.println("═══════════════════════════════════════════");
System.out.println(" " + companyName);
System.out.println(" JDK 8 开发环境自检程序 " + checkerVersion);
System.out.println("═══════════════════════════════════════════");
System.out.println();
// 检查1:Java版本
String javaVersion = System.getProperty("java.version");
System.out.print("【检查1】Java 版本 : ");
System.out.println(javaVersion);
if (!javaVersion.startsWith("1.8")) {
System.out.println(" ⚠ 警告:非JDK 8版本!本教程基于JDK 8。");
allPassed = false;
} else {
System.out.println(" ✓ JDK 8版本正确");
}
// 检查2:Java厂商
String javaVendor = System.getProperty("java.vendor");
System.out.print("【检查2】Java 厂商 : ");
System.out.println(javaVendor);
// 检查3:JAVA_HOME环境变量
String javaHome = System.getProperty("java.home");
System.out.print("【检查3】java.home 系统属性 : ");
System.out.println(javaHome);
String envJavaHome = System.getenv("JAVA_HOME");
System.out.print("【检查4】JAVA_HOME 环境变量 : ");
if (envJavaHome != null) {
System.out.println(envJavaHome);
System.out.println(" ✓ JAVA_HOME 已配置");
} else {
System.out.println("(未设置)");
System.out.println(" ⚠ 建议配置JAVA_HOME,方便Tomcat/Maven等工具使用");
allPassed = false;
}
// 检查4:JVM内存
long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;
System.out.print("【检查5】JVM 最大可用内存 : ");
System.out.println(maxMemory + " MB");
// 检查5:可用处理器数
int processors = Runtime.getRuntime().availableProcessors();
System.out.print("【检查6】可用处理器核心数 : ");
System.out.println(processors + " 核");
// 检查6:时区
String timezone = System.getProperty("user.timezone");
System.out.print("【检查7】用户时区 : ");
System.out.println(timezone != null ? timezone : "(未设置)");
// 检查7:文件编码
String fileEncoding = System.getProperty("file.encoding");
System.out.print("【检查8】默认文件编码 : ");
System.out.println(fileEncoding);
if (!"UTF-8".equalsIgnoreCase(fileEncoding)) {
System.out.println(" ⚠ 建议在IDEA中设置文件编码为UTF-8,避免中文乱码");
}
// 最终结论
System.out.println();
System.out.println("═══════════════════════════════════════════");
if (allPassed) {
System.out.println(" 检查结果:✓ 全部通过!可以开始Java开发了。");
} else {
System.out.println(" 检查结果:⚠ 存在警告,请根据上述提示处理。");
}
System.out.println(" 愿你朝华相顾,愿你前程似锦。");
System.out.println("═══════════════════════════════════════════");
}
}
运行输出(正确配置的Windows环境):
═══════════════════════════════════════════
广州飞翔科技
JDK 8 开发环境自检程序 v1.0
═══════════════════════════════════════════
【检查1】Java 版本 : 1.8.0_202
✓ JDK 8版本正确
【检查2】Java 厂商 : Oracle Corporation
【检查3】java.home 系统属性 : C:\Program Files\Java\jdk1.8.0_202\jre
【检查4】JAVA_HOME 环境变量 : C:\Program Files\Java\jdk1.8.0_202
✓ JAVA_HOME 已配置
【检查5】JVM 最大可用内存 : 1820 MB
【检查6】可用处理器核心数 : 8 核
【检查7】用户时区 : Asia/Shanghai
【检查8】默认文件编码 : GBK
⚠ 建议在IDEA中设置文件编码为UTF-8,避免中文乱码
═══════════════════════════════════════════
检查结果:⚠ 存在警告,请根据上述提示处理。
愿你朝华相顾,愿你前程似锦。
═══════════════════════════════════════════
核心原理:JVM为什么能找到并执行你的.class文件
类加载的查找路径
JVM启动后需要加载Hello.class,它按以下顺序查找:
| 类加载器 | 负责范围 | 查找路径 |
|---|---|---|
| Bootstrap ClassLoader | Java核心类库 | %JAVA_HOME%/jre/lib/rt.jar |
| Extension ClassLoader | Java扩展库 | %JAVA_HOME%/jre/lib/ext/ |
| Application ClassLoader | 用户自定义类 | CLASSPATH环境变量(默认含.当前目录) |
Path vs CLASSPATH 的本质区别
| 维度 | Path | CLASSPATH |
|---|---|---|
| 作用对象 | 操作系统 | JVM |
| 查找什么 | 可执行文件(.exe) | Java类文件(.class)和jar包 |
| 用途 | 找到javac.exe和java.exe | 找到编译/运行时依赖的类 |
| 默认值 | 操作系统自带路径 | 当前目录. |
| 分隔符 | 分号;(Windows) | 分号;(Windows) |
记忆口诀:"Path找命令,CLASSPATH找类"。
第二个代码示例:使用-cp指定类路径
飞翔科技的项目结构如下,白歌教小崔如何用-cp参数:
C:\Users\xiaocui\feixiang-project\
├── src\
│ └── com\
│ └── feixiang\
│ └── CompanyInfo.java
└── classes\ ← 编译输出目录
package com.feixiang;
/**
* CompanyInfo.java
* 路径: src/com/feixiang/CompanyInfo.java
* 场景:飞翔科技项目中的公司信息类
*/
public class CompanyInfo {
private String companyName = "广州飞翔科技";
private int foundedYear = 2018;
private String domain = "www.feixiang.net";
private int employeeCount = 12;
public void printInfo() {
System.out.println("═══════════════════════════════");
System.out.println(" 公司名称 : " + companyName);
System.out.println(" 成立年份 : " + foundedYear + " 年");
System.out.println(" 官方网站 : " + domain);
System.out.println(" 员工人数 : " + employeeCount + " 人");
System.out.println("═══════════════════════════════");
}
public static void main(String[] args) {
CompanyInfo info = new CompanyInfo();
info.printInfo();
System.out.println("愿你朝华相顾,愿你前程似锦。");
}
}
编译和运行命令(带包路径):
# 步骤1:进入项目根目录
C:\Users\xiaocui> cd feixiang-project
# 步骤2:编译(-d 指定输出目录到classes)
C:\Users\xiaocui\feixiang-project> javac -d classes src\com\feixiang\CompanyInfo.java
# 步骤3:运行(-cp 指定类路径为classes目录)
C:\Users\xiaocui\feixiang-project> java -cp classes com.feixiang.CompanyInfo
运行输出:
═══════════════════════════════
公司名称 : 广州飞翔科技
成立年份 : 2018 年
官方网站 : www.feixiang.net
员工人数 : 12 人
═══════════════════════════════
愿你朝华相顾,愿你前程似锦。
注意:运行带
package的类时,必须使用完全限定名com.feixiang.CompanyInfo,且类路径必须指向包的根目录(classes/),而非.class文件所在目录。
易错场景与面试考点
反例一:JAVA_HOME配成了bin目录
# ❌ 错误配置
JAVA_HOME = C:\Program Files\Java\jdk1.8.0_202\bin # 多了\bin!
# 后果
# 很多依赖JAVA_HOME的工具(如Maven、Tomcat)会拼接 %JAVA_HOME%\bin\java.exe
# 拼接后就变成了 C:\...\jdk1.8.0_202\bin\bin\java.exe → 找不到!
纠正:
# ✅ 正确配置
JAVA_HOME = C:\Program Files\Java\jdk1.8.0_202 # JDK根目录,不含bin
反例二:配置完环境变量后没开新命令行
# ❌ 错误:在同一个命令行窗口验证
C:\Users\xiaocui> set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_202
C:\Users\xiaocui> javac -version
'javac' 不是内部或外部命令... # 刚配的没生效?
原因:Windows命令提示符在启动时读取环境变量。通过"系统属性"修改后,必须重新打开cmd窗口才能生效。
反例三:Path中已有其他Java路径的冲突
# ❌ 错误:Path中有多个Java路径
C:\Users\xiaocui> where java
C:\Program Files\Java\jdk1.8.0_202\bin\java.exe ← 想要的
C:\Program Files (x86)\Common Files\Oracle\Java\javapath\java.exe ← 捣乱的(旧版)
C:\Users\xiaocui> java -version
java version "9.0.4" # 不是预期的8!
纠正:将%JAVA_HOME%\bin移到Path变量的最前面,或删除其他Java路径。
面试高频题
Q1:JAVA_HOME 和 Path 有什么区别?为什么要配JAVA_HOME?
Path是操作系统级别的环境变量,让命令行能找到javac.exe和java.exe。JAVA_HOME不是操作系统必需的,但它是Java生态的约定标准——Tomcat、Maven、Gradle、Eclipse、IntelliJ IDEA等工具都通过JAVA_HOME来定位JDK安装目录。如果只配Path不配JAVA_HOME,用命令行可以编译运行,但上述工具可能找不到JDK。
Q2:CLASSPATH 环境变量和 java -cp 参数有什么区别?
CLASSPATH环境变量是全局生效的,一旦设置会影响所有Java程序。java -cp(或java -classpath)是命令行级别的,只影响当次运行。推荐使用-cp参数,因为全局CLASSPATH容易被遗忘、导致跨项目类冲突或版本不一致。
Q3:为什么有时候 java Hello 报"NoClassDefFoundError"?
最常见原因:① 类路径不对——运行
java Hello时,当前目录下没有Hello.class;② 类名写错——大小写敏感(Hello和hello是不同的);③ 包路径问题——类声明了package com.feixiang;但直接运行java Hello,应该用java com.feixiang.Hello且类路径指向包的根目录;④ CLASSPATH 缺少.——即使配置了CLASSPATH,也必须包含.表示当前目录。
Q4:javac 和 java 命令分别做了什么事?
javac是Java编译器,负责将.java源代码文件编译为.class字节码文件。编译过程包括:词法分析 → 语法分析 → 语义分析 → 生成字节码。java命令启动JVM,加载.class字节码文件并执行其中的main方法。如果指定的是.jar文件,JVM从META-INF/MANIFEST.MF中读取Main-Class入口。
本章小结:JDK包含JRE,JRE包含JVM。JAVA_HOME指向JDK安装根目录,Path确保命令行能找到javac/java命令,CLASSPATH告诉JVM到哪里找.class文件(推荐用
-cp代替全局CLASSPATH)。两个核心验证命令:java -version和javac -version。配置完记得重新打开命令行窗口。