Skip to content

JDK 从 0 到 1 完整学习手册

学习目标:能用一句话向产品经理讲清楚「JDK 到底是个什么玩意儿」;能向面试官讲清楚「JDK / JRE / JVM 三者到底啥区别」;理解一份 .java 源码是怎么被编译、装载、执行起来的;遇到 JAVA_HOME 环境变量没配版本不兼容内存溢出 这类常见问题不再两眼一抹黑。


0. 一张图看懂全文

   你写的代码                 JDK 帮你做的事                  最终的样子
  ─────────────             ─────────────────              ─────────────
   Hello.java   ──── javac ────►   Hello.class   ──── java ────►  屏幕打印 Hello
   (人能看懂)        编译器          (JVM 能看懂)       虚拟机           (程序运行起来)
                                  字节码 bytecode

📌 生活化类比:你写菜谱(.java)是给中国厨师看的中文,但餐厅的机器人厨师(JVM)只认识一套国际通用的「图形菜谱」(.class 字节码)。JDK 就是那本"中文菜谱 → 图形菜谱"的翻译手册 + 机器人厨师 + 一整套厨房工具的合集


1. JDK 是什么:一句话讲清

JDK(Java Development Kit,Java 开发工具包)是 Oracle / OpenJDK 等组织发行的一整套"开发 + 运行 Java 程序"所需要的全家桶,包含编译器、运行时(JRE)、调试工具、文档工具和标准类库。

这句话拆开看:

含义通俗类比
Development Kit开发工具包像「装修工具箱」,里面有锤子、电钻、卷尺、说明书
编译器(javac).java 翻译成 .class「翻译官」
运行时(JRE + JVM)真正跑程序的环境「执行命令的厨房」
调试工具(jdb / jps / jstack)排查问题用「显微镜 + 听诊器」
标准类库(rt.jar / java.base 等)一堆别人写好的代码(String、List、HashMap……)「半成品冷柜」,拿来就能用

2. JDK / JRE / JVM 三者关系(面试高频)

这是 Java 入门第一个让人懵的概念。一张图一辈子记住:

   ┌────────────────────────────────────────────────────────┐
   │                          JDK                            │
   │                  (开发 + 运行的全家桶)                  │
   │                                                         │
   │   ┌──────────────────────────────────────────────┐     │
   │   │                    JRE                        │     │
   │   │              (只能"运行"程序)                 │     │
   │   │                                                │     │
   │   │     ┌──────────────────────────────────┐      │     │
   │   │     │              JVM                  │      │     │
   │   │     │      (执行字节码的虚拟机)          │      │     │
   │   │     └──────────────────────────────────┘      │     │
   │   │                                                │     │
   │   │     +  Java 标准类库(String/List/HashMap..)   │     │
   │   └──────────────────────────────────────────────┘     │
   │                                                         │
   │   +  开发工具:javac / javadoc / jar / jdb / jps ...    │
   └────────────────────────────────────────────────────────┘

2.1 用一个外卖的故事讲明白

角色对应干什么
JVM厨房的灶台真正"做菜"的地方,把字节码烹熟变成程序运行
JRE厨房(灶台 + 食材冷柜)灶台 + 一冷柜半成品(标准类库),能直接做现成的菜,但不能开发新菜
JDK整个餐厅(厨房 + 研发部 + 工具间)既能做菜也能研发新菜,给开发者用

2.2 那我电脑上到底装哪个?

你的角色             需要装什么
─────────────       ─────────────────
普通用户              JRE 就够(很多年前 Java 小程序时代)
                    (现在已经基本不再单独发行 JRE 了)

Java 开发者          JDK 必装

服务器跑 Java 程序    JDK 或 JRE 都行,但实际工作中
                    一律装 JDK(方便排查问题用 jstack/jstat)

📌 重要事实:从 JDK 11 开始,Oracle 不再单独发布 JRE,JDK 自带运行能力。所以现在你只需要装 JDK 就够了。


3. JDK 简史与版本选择

3.1 30 秒版编程史

1995 ── Java 1.0 (Sun Microsystems) "一次编写,到处运行"             ★ 时代开端
1998 ── Java 1.2 引入 Swing/Collections,史称 J2SE 1.2
2004 ── Java 5  ★ 泛型、注解、自动装箱、枚举、增强 for(划时代)
2006 ── Sun 把 JDK 开源,叫 OpenJDK
2010 ── Oracle 收购 Sun,Java 易主
2014 ── Java 8  ★★★ Lambda、Stream、Optional(至今最经典版本)
2017 ── Java 9  模块化 (JPMS),砍掉了一些祖传 API
2018 ── ★ Oracle 调整商业策略:Oracle JDK 商用收费,OpenJDK 免费
2018 ── Java 11 ★★ 第一个 LTS(长期支持),公司大量从 8 迁过来
2021 ── Java 17 ★★ LTS,Record / Sealed / 模式匹配 全面成熟
2023 ── Java 21 ★★★ LTS,虚拟线程(Loom)、模式匹配 GA,"现代 Java" 起点
2025 ── Java 25 LTS(每 2 年一个 LTS)

3.2 LTS 是什么?

LTS = Long Term Support 长期支持版,可以理解为「官方承诺免费修 BUG 好多年」的稳定版。每 6 个月发一个新版本,但只有特定的几个版本是 LTS。

   非 LTS 版本:      用了就像追新番,过半年就停更,bug 没人修
   LTS 版本:         用了就像追长篇连载,连续好几年都有人维护

   主流 LTS:8  →  11  →  17  →  21  →  25
   (8 已停止免费商用支持,但是 2030 年前 OpenJDK 8 还有社区维护)

📌 生活化类比:买手机你愿意买年度旗舰还是季度试验机?LTS 就是「年度旗舰」,公司生产环境一定挑 LTS 用。

3.3 该选哪个版本?给小白的「无脑公式」

新项目从零开始:     用 JDK 21(最新 LTS,未来 5 年不操心)
维护老项目:         看老项目本来用啥就用啥(一般是 8 / 11 / 17)
学 Android:         JDK 17(Android Studio 现在自带 JBR 17)
学 Spring Boot 3.x: 必须 JDK 17+
公司服务器:         JDK 17 或 JDK 21(看公司基础设施)

3.4 JDK 厂商有哪些?该装哪个发行版?

很多人不知道:JDK 不止 Oracle 一家做,OpenJDK 是开源标准,每家公司基于它都可以编译自己的发行版。

发行版厂商收费?推荐场景
Oracle JDKOracle商用要钱(JDK 17 以后又部分免费了)老项目存量
OpenJDKOpenJDK 社区完全免费通用
Eclipse Temurin(前 AdoptOpenJDK)Eclipse 基金会完全免费个人 / 公司首选
Amazon Corretto亚马逊完全免费AWS 用户
Azul ZuluAzul免费版 + 商用版性能敏感场景
JetBrains Runtime (JBR)JetBrains免费IntelliJ / Android Studio 内置
GraalVMOracle免费想编译成本地可执行文件

📌 新手无脑选:直接装 Eclipse Temurin 最新 LTS(21)。不用纠结。


4. JDK 内部到底有些啥?

下载完一个 JDK,解压后是一坨文件夹。我们解剖一下(以 JDK 17+ 为例):

   jdk-21/
   ├── bin/                 ★ 所有可执行命令(javac、java、jar、jps...)
   ├── conf/                  配置文件(安全策略、日志)
   ├── include/               C/C++ 头文件(写 JNI 时要)
   ├── jmods/                 模块文件(JDK 9 模块化后的产物)
   ├── lib/                   底层依赖库(含一些 .so / .dll)
   ├── legal/                 各种开源协议
   └── release                版本信息

最有用的就是 bin/ 这一坨,挑几个真的会用到的命令讲讲:

命令干啥的通俗类比
javacJava 编译器:.java → .class翻译官
java启动 JVM 运行字节码厨师按菜谱做菜
jar把一堆 .class 打包成 .jar装快递箱
javadoc从注释生成 API 文档自动写说明书
jps查看本机所有 Java 进程ps -ef | grep java 的 Java 专用版
jstack打印线程堆栈给程序拍 X 光,查"卡在哪了"
jmap导出堆内存快照拍内存的 CT 片
jstat查看 GC 统计看程序的"心电图"
jcmd万能瑞士军刀(替代上面好多命令)多功能遥控器
jdb命令行调试器老派调试工具,IDE 出来后基本不用
jshellJDK 9 加的交互式 REPL像 Python 那样可以一行一行试代码

4.1 一定要学会的 3 个命令

java -version —— 查当前用的什么版本

bash
$ java -version
openjdk version "21.0.2" 2024-01-16 LTS
OpenJDK Runtime Environment Temurin-21.0.2+13 (build 21.0.2+13-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.2+13 (build 21.0.2+13-LTS, mixed mode, sharing)

jps —— 看有哪些 Java 程序在跑

bash
$ jps -lv
12345 org.apache.catalina.startup.Bootstrap -Xmx2g
67890 com.example.MyApp -Xms512m

jshell —— 不用建工程也能写 Java

bash
$ jshell
jshell> 1 + 1
$1 ==> 2

jshell> "hello".toUpperCase()
$2 ==> "HELLO"

jshell> /exit

📌 生活化类比:以前学 Java 必须先写一个 class HelloWorld { public static void main... } 框架代码才能跑一行。jshell 出来后,终于跟 Python 一样想到啥就试啥,对小白超友好。


5. 装 JDK + 配环境变量

5.1 三步装好(以 macOS / Linux 为例)

bash
# 1. 下载(推荐 Temurin)
# 去 https://adoptium.net/ 下对应平台的 .tar.gz / .pkg / .msi

# 2. 解压(举例 Linux)
sudo tar -zxvf OpenJDK21U-jdk_x64_linux_hotspot.tar.gz -C /opt/

# 3. 配环境变量(写到 ~/.bashrc 或 ~/.zshrc)
export JAVA_HOME=/opt/jdk-21.0.2+13
export PATH=$JAVA_HOME/bin:$PATH

# 4. 立刻生效
source ~/.zshrc

# 5. 验证
java -version
javac -version

Windows 用户:装个 .msi 安装包,安装时勾选「设置 JAVA_HOME」就行;或者手动到「系统属性 → 环境变量」加 JAVA_HOMEPATH

5.2 JAVA_HOME 到底是个啥?为什么要配?

   JAVA_HOME = JDK 装在哪个文件夹的"地址簿"
   PATH      = 系统去哪儿找命令的"路径列表"

📌 生活化类比

  • JAVA_HOME 像「Java 大本营在 X 路 Y 号」这块路牌
  • PATH 像「外卖小哥的送货地图」,告诉系统:「用户敲 java 命令时,到 $JAVA_HOME/bin 这个路径里去找」

不配 JAVA_HOME很多软件(Tomcat、Maven、Gradle、Android Studio)找不到 Java 装在哪里,就罢工。

5.3 多版本共存:jenv / sdkman(高级技巧)

工作中你可能同时维护 JDK 8 的老项目和 JDK 21 的新项目,怎么切换?

Linux / macOS 推荐 sdkman

bash
# 装 sdkman
curl -s "https://get.sdkman.io" | bash

# 列出所有可装的 JDK
sdk list java

# 装一个
sdk install java 21.0.2-tem
sdk install java 17.0.10-tem
sdk install java 8.0.402-tem

# 切换
sdk use java 17.0.10-tem      # 仅当前终端
sdk default java 21.0.2-tem   # 全局默认

📌 生活化类比sdkman 像「JDK 版本的 nvm / pyenv」,手电筒一按就切灯泡,不用每次手改 JAVA_HOME


6. 一段代码完整跑起来:从源码到屏幕

让我们手把手把一个程序从代码到运行全程跟一遍,不用 IDE,纯命令行,这样你能看清 JDK 每一步在干嘛。

6.1 写代码

新建一个文件 Hello.java

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

6.2 编译

bash
$ javac Hello.java
# 没报错 = 成功,当前目录会多一个 Hello.class 文件
$ ls
Hello.java   Hello.class

Hello.class 长这样(截取片段)—— 不是给人看的,是给 JVM 看的字节码

ca fe ba be 00 00 00 41 00 1d 0a 00 02 00 03 07
00 04 0c 00 05 00 06 01 00 10 6a 61 76 61 2f 6c
...

注意开头四个字节 CA FE BA BE —— 这是 Java class 文件的"魔数",类似身份证号,JVM 看到这四个字节才认它是合法字节码。

📌 生活化类比CA FE BA BE 拼读起来像 "Cafe Babe(咖啡宝贝)",因为 Java 的 logo 就是一杯咖啡。这是 Sun 工程师当年埋的彩蛋,至今没改过。

6.3 运行

bash
$ java Hello       # 注意没有 .class 后缀!
Hello, JDK!

幕后发生了什么?三大步:

   ┌─────────────────────────────────────────────────────────────┐
   │  Step 1:类加载器(ClassLoader)找到 Hello.class,读进内存    │
   │                                                              │
   │  Step 2:字节码校验器(Verifier)检查这是合法字节码吗?        │
   │          有没有"非法访问"、"栈溢出"等可疑动作?              │
   │                                                              │
   │  Step 3:执行引擎运行 main 方法                              │
   │          → 解释器逐条执行 / 热代码 JIT 编译为机器码           │
   │          → CPU 执行机器码,屏幕上看到 "Hello, JDK!"          │
   └─────────────────────────────────────────────────────────────┘

6.4 反编译看看 .class 里到底是啥(拓展)

JDK 自带 javap 工具:

bash
$ javap -c Hello
Compiled from "Hello.java"
public class Hello {
  public Hello();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #7        // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #13       // String Hello, JDK!
       5: invokevirtual #15       // Method java/io/PrintStream.println:(...)V
       8: return
}

这些 aload_0 / invokevirtual 就是字节码指令,类似汇编但跨平台 —— 这正是 Java「Write Once, Run Anywhere(一次编写,到处运行)」的秘密。

📌 生活化类比:Windows 的 .exe 像粤语,只有广东人听得懂;Linux 的 ELF 像川话,只有四川人听得懂。Java 字节码像「普通话」,全世界 JVM 都能听懂,所以你的程序拿到任何系统装上 JVM 就能跑。


7. JVM 工作原理(小白版)

JVM 是 JDK 里最神秘也最重要的部分。我们用「餐厅运营」的类比来理解。

7.1 JVM 的三大组件

   ┌────────────────────────────────────────────────────────┐
   │                       JVM                              │
   │                                                         │
   │   ┌─────────────┐  ┌──────────────┐  ┌──────────────┐ │
   │   │ 类加载子系统  │ │  运行时数据区   │ │  执行引擎     │ │
   │   │ ClassLoader │ │  Runtime Data │ │ Execution    │ │
   │   │             │ │  Areas        │ │ Engine       │ │
   │   └─────────────┘ └──────────────┘ └──────────────┘ │
   │   把 .class 装入   程序运行时的"内存"  解释 + JIT 编译 + GC│
   └────────────────────────────────────────────────────────┘
组件干啥的餐厅类比
类加载器.class 从磁盘读进内存「采购员」从仓库取食材
运行时数据区划分各种内存区域「厨房工作台」分蔬菜区、肉区、酱料区
执行引擎真正执行字节码「厨师」按菜谱做菜

7.2 运行时数据区:内存怎么划分

这是面试经典问题:「JVM 内存模型有哪几块?」

   ┌──────────────────────────────────────────────────────────┐
   │                       JVM 内存                            │
   │                                                           │
   │   ┌──────────┐ ┌──────────┐ ┌──────────────────────────┐ │
   │   │ 程序计数器 │ │ Java 栈   │ │      Java 堆             │ │
   │   │ 每线程私有 │ │ 每线程私有 │ │   所有线程共享             │ │
   │   │          │ │          │ │   ★ 对象都在这里           │ │
   │   └──────────┘ └──────────┘ │   ★ GC 的主战场            │ │
   │   ┌──────────┐ ┌──────────┐ │                          │ │
   │   │ 本地方法栈 │ │ 元空间    │ │                          │ │
   │   │ 每线程私有 │ │(方法区)  │ │                          │ │
   │   │          │ │ 类元数据  │ │                          │ │
   │   └──────────┘ └──────────┘ └──────────────────────────┘ │
   └──────────────────────────────────────────────────────────┘
区域存什么通俗类比出问题会咋样
程序计数器 PC当前线程执行到第几行字节码看书时的"书签"几乎不会出错
Java 栈方法调用、局部变量厨师做菜的"工序笔记本",做完一道菜撕一页StackOverflowError(递归太深)
本地方法栈调 C/C++ 代码(JNI)时用餐厅请的"外援大厨"用的工作台同上
Java 堆所有 new 出来的对象餐厅的"成品冷柜",菜做好都放这OutOfMemoryError: Java heap space
方法区 / 元空间类的元信息、常量池、静态变量"菜谱图书馆"OutOfMemoryError: Metaspace(动态加载太多类)

📌 关键记忆:「对象在堆上,引用在栈上」。

比如 User u = new User(); 这行:

  • new User() 创建的对象在
  • u 这个变量名(指向那个对象的"快递单号")在

7.3 GC:垃圾回收(最神奇的部分)

C/C++ 程序员要手动 malloc / free 内存,写错就内存泄漏。Java 不用,因为 JVM 会自动收垃圾。

啥是「垃圾」?

没有任何变量再指向它的对象 = 垃圾

java
User u = new User();   // 此时堆上有一个 User 对象,u 指向它,不是垃圾
u = null;              // 没人指向它了 → 变成垃圾,下次 GC 时被回收

GC 的两种基本算法

   算法 1:标记-清除
   ──────────────────
   先扫一遍,标记所有"还有人用"的对象 → 把没标记的扫掉
   缺点:内存碎片化,像房间打扫完家具东一块西一块

   算法 2:复制(Copying)
   ──────────────────
   把内存切成 A / B 两半,活对象从 A 复制到 B,A 整个清空
   缺点:浪费一半内存

   现代 JVM 都是组合拳:分代 + 复制 + 标记整理

「分代收集」是什么?

JVM 的工程师发现一个统计规律:「绝大部分对象创建后很快就死了」,比如临时变量。所以他们把堆分两块:

   ┌─────────────────────────────────────────────────────────┐
   │                       Java 堆                            │
   │                                                          │
   │   ┌────────────────────────┐  ┌──────────────────────┐ │
   │   │     新生代 (Young)      │  │    老年代 (Old)        │ │
   │   │  小、扫得快、扫得勤      │ │  大、扫得慢、扫得少    │ │
   │   │                        │  │                      │ │
   │   │  Eden + S0 + S1         │  │   长寿对象的家         │ │
   │   └────────────────────────┘  └──────────────────────┘ │
   └─────────────────────────────────────────────────────────┘

   生命周期:
   1. new 出来的对象先放 Eden 区
   2. 第 1 次 GC 没死 → 挪到 S0
   3. 第 2 次 GC 没死 → 挪到 S1
   4. 反复 N 次都不死 → 升级到老年代("老人区")
   5. 老年代满了 → Full GC(重量级回收,会"暂停整个程序")

📌 生活化类比:JVM 的 GC 像幼儿园 + 养老院两套机制:

  • 幼儿园(新生代)的小朋友很多,但流动性大,老师每天都要清点(Minor GC)
  • 养老院(老年代)的老人少而稳定,几个月才大检查一次(Full GC)

把人按年龄分开管,效率比"全市统一普查"高得多。

常见垃圾收集器(了解即可)

收集器出现年代特点适用
Serial远古单线程,简单小程序
ParallelJDK 5 默认多线程,吞吐优先后台批处理
CMSJDK 5(已废弃)并发标记清除,低延迟已退役
G1JDK 7 引入 / JDK 9 默认分区、可预测停顿大堆通用首选
ZGCJDK 11 引入超大堆 + 几乎不停顿(< 1ms)TB 级堆
ShenandoahRedHat 出品类似 ZGC同上

📌 小白不用记:现代 JDK 默认 G1,绝大部分情况不用调;遇到性能问题再说。


8. 类加载机制(面试常考)

8.1 加载过程

一个 .class 文件要变成 JVM 能跑的样子,要走 5 步:

   ┌───────┐   ┌───────┐   ┌───────┐   ┌──────────┐   ┌────────┐
   │ 加载  │ → │ 验证  │ → │ 准备  │ → │ 解析      │ → │ 初始化 │
   └───────┘   └───────┘   └───────┘   └──────────┘   └────────┘
   读入字节   合法吗?     给静态变量    符号引用      执行
                        分配默认值    转直接引用    static 块

8.2 双亲委派模型

JVM 不是"看到一个 .class 就直接加载",它有一套等级森严的加载顺序:

              ┌───────────────────────┐
              │  启动类加载器           │  ★ 最权威,只加载 java.* 这些核心
              │  Bootstrap ClassLoader │
              └───────────┬───────────┘

              ┌───────────▼───────────┐
              │  扩展类加载器           │  加载 javax.* 等扩展库
              │  Extension/Platform   │
              └───────────┬───────────┘

              ┌───────────▼───────────┐
              │  应用类加载器           │  加载你写的代码(classpath)
              │  Application          │
              └───────────────────────┘

   工作流程:你想加载一个类
   → 先问爹(应用 → 扩展 → 启动):「你能加载吗?」
   → 爹不能加载,自己再尝试
   → 这样保证 java.lang.String 永远是 JDK 自带那个,
     不会被你写的同名类替换掉(防恶意代码)

📌 生活化类比:这套机制像家族式公司的请示流程 —— 任何决策先逐级上报到董事长(Bootstrap),董事长说"我管不了"才轮到下面办。这样保证核心规则永远由最高层制定,下面没法偷偷篡改。


9. 实战:常见问题排查工具箱

学这一节,你下次看到线上报错就不慌了。

9.1 程序卡死了,怎么看「卡在哪」?

bash
# 第 1 步:找到 Java 进程的 PID
$ jps -l
12345 com.example.MyApp

# 第 2 步:打印所有线程的堆栈
$ jstack 12345 > stack.txt

# 第 3 步:打开 stack.txt 找 BLOCKED / WAITING 的线程
# 通常一眼能看出"哪个线程卡在哪个方法"

9.2 内存爆了:OutOfMemoryError

bash
# 第 1 步:启动 Java 时加参数,让它崩的时候自动 dump 内存
$ java -Xmx2g \
       -XX:+HeapDumpOnOutOfMemoryError \
       -XX:HeapDumpPath=/tmp/heap.hprof \
       MyApp

# 第 2 步:用 Eclipse MAT 或 VisualVM 打开 .hprof 文件
# 看「哪个对象占了大头」「谁在持有它不让 GC 收」

9.3 想看 GC 日志

bash
# JDK 9+ 统一日志格式
$ java -Xlog:gc*:file=gc.log:time,uptime,level,tags MyApp

# 然后用 GCEasy.io(在线工具)上传 gc.log,自动出可视化报告

9.4 常用启动参数速记表

参数作用例子
-Xms<n>初始堆大小-Xms512m
-Xmx<n>最大堆大小-Xmx2g
-Xss<n>单线程栈大小-Xss1m
-XX:+PrintGCDetails打印 GC 详情(JDK 9 后用 -Xlog:gc*
-XX:+HeapDumpOnOutOfMemoryErrorOOM 时自动 dump必加
-Dprop=val设系统属性-Dfile.encoding=UTF-8

📌 生产环境通用模板

bash
java -Xms2g -Xmx2g \
     -XX:+UseG1GC \
     -XX:+HeapDumpOnOutOfMemoryError \
     -XX:HeapDumpPath=/data/logs/heap.hprof \
     -Xlog:gc*:file=/data/logs/gc.log:time,level,tags \
     -jar myapp.jar

10. 常见疑惑 FAQ

Q1:我电脑上装了好几个 JDK,到底用的哪个?

bash
$ which java               # 看 java 命令实际指向哪
$ java -version            # 看版本
$ echo $JAVA_HOME          # 看 JAVA_HOME 配的哪个

如果 JAVA_HOME 配的版本和 java -version 不一样,是因为 PATH 里有别的版本排在前面。

Q2:JDK 8 和 JDK 17 能装在同一台电脑吗?

完全可以。 装在不同目录,用 sdkman / jenv 切换,或者每个项目用 JAVA_HOME 指向不同 JDK。

Q3:Maven / Gradle 用哪个 JDK?

它们用的是启动它们时的那个 JDK(即 java 命令对应的版本)。 项目可以单独指定编译版本(maven-compiler-pluginsource/target 或 Gradle 的 sourceCompatibility),但这只影响编译产物的字节码版本,不影响运行 Maven/Gradle 本身的 JDK。

Q4:为啥同一个 .class 拿去 JDK 8 跑就报 UnsupportedClassVersionError

因为字节码有版本号。JDK 11 编译的 .class 默认版本是 55,JDK 8 的 JVM 只认 52 及以下。

解决:编译时降级
  javac --release 8 Hello.java        # JDK 9+ 推荐
  javac -source 8 -target 8 Hello.java  # 老写法

📌 生活化类比:你用 Word 2021 存了 .docx,拿到 Word 2003 打不开。一样的道理。

Q5:为啥学 Kotlin / Scala / Groovy 也要装 JDK?

因为它们都编译成 JVM 字节码,最终都跑在 JVM 上,所以离不开 JDK

Q6:JDK 和 OpenJDK 是同一个东西吗?

OpenJDK 是开源标准实现,所有发行版(Oracle JDK / Temurin / Corretto)都基于 OpenJDK,差别只在打包、商业支持、补丁速度。功能上 99.9% 一致


11. 学习路线图

   第 1 周:环境 + 基本概念(本文 1~6 章)
   ├─ 装好 Temurin JDK 21
   ├─ 跑通 Hello.java 命令行编译运行
   └─ 理解 JDK / JRE / JVM 关系

   第 2~4 周:Java 基础语法
   ├─ 变量、控制流、面向对象、集合、IO
   └─ 推荐书:《On Java 8》中文叫《Java 编程思想 第 5 版》

   第 5~8 周:Java 进阶
   ├─ 多线程、JUC 并发包
   ├─ 反射、注解、泛型
   ├─ Stream / Lambda / Optional
   └─ 推荐:《Effective Java 第 3 版》

   第 9~12 周:JVM 深度
   ├─ 内存模型、GC、类加载(本文 7~9 章 + 深挖)
   ├─ 用 JFR (Java Flight Recorder) 实战分析
   └─ 推荐:《深入理解 Java 虚拟机 第 3 版》(周志明)

   第 13 周以后:根据方向选择
   ├─ 后端 → Spring Boot / Spring Cloud
   ├─ Android → 跟 Kotlin 一起学
   ├─ 大数据 → Hadoop / Flink / Spark
   └─ 中间件 → Netty / Dubbo

12. 必读参考资源

类型推荐
官网https://openjdk.org
下载https://adoptium.net (Temurin)
在线 API 文档https://docs.oracle.com/en/java/javase/21/docs/api/
入门书《Head First Java》《On Java 8》
JVM 圣经《深入理解 Java 虚拟机》周志明
代码风格《Effective Java 第 3 版》Joshua Bloch
JEP 索引(看新版本加了啥)https://openjdk.org/jeps/0

13. 一句话总结

JDK 是 Java 世界的全套装备JVM 是发动机JRE 是发动机 + 油箱 + 标配工具JDK 是 JRE + 整套维修工具。 普通用户用 JRE,开发者必装 JDK;想跑 Kotlin / Scala / Spring 的,统统离不开它。

学 JDK 不是学一门语言,是学一台「跨平台运行机器」是怎么诞生、怎么工作、怎么被排查问题的。理解了它,你写的每一行 Java / Kotlin 代码背后是什么样子,就再也不是黑盒了。