第3章:模块化JDK:JDK模块结构与核心模块
JDK 9 将自身拆分为一系列模块,彻底告别传统的“单一JAR(如 rt.jar
)”模式。本章深入解析 JDK 的模块化架构、核心模块功能及开发者如何高效利用这些模块。
3.1 JDK 模块化设计概览
设计目标
- 模块化拆分:将 JDK 代码库划分为 94 个独立模块(JDK 17 扩展至约 100 个)。
- 强封装:隐藏内部 API(如
sun.misc
),仅公开标准 API。 - 按需加载:允许应用仅依赖所需模块,减少运行时内存占用。
模块分类
JDK 模块分为三类:
- 标准模块(Standard Modules):以
java.*
开头的模块(如java.base
),提供核心 API。 - JDK 专用模块(JDK-specific Modules):以
jdk.*
开头的模块(如jdk.unsupported
),包含 JDK 实现细节。 - 聚合模块(Aggregator Modules):如
java.se
,仅用于聚合其他模块,无实际代码。
3.2 核心模块详解
javabase_23">1. java.base
(基础核心模块)
- 功能:包含 Java 最基础的类库,如
Object
、String
、集合框架、IO/NIO、安全等。 - 特性:
- 示例:
java">// 任何模块自动依赖 java.base module com.myapp {// 无需 requires java.baseexports com.myapp.api; }
javasql_37">2. java.sql
(数据库连接模块)
- 功能:提供 JDBC API(
Connection
、Statement
、ResultSet
)。 - 依赖:
java">module com.myapp {requires java.sql; // 显式声明依赖 }
javanethttpHTTP__46">3. java.net.http
(HTTP 客户端模块)
- 功能:JDK 9 新增的 HTTP/2 客户端(非孵化器版本需 JDK 11+)。
- 示例:
java">module com.myapp {requires java.net.http; }
4. jdk.unsupported
(非标准支持模块)
- 功能:提供对部分内部 API 的临时访问(如
sun.misc.Unsafe
),但强烈不建议使用。 - 警告:此模块可能在未来的 JDK 版本中被移除或调整。
3.3 模块依赖关系与查看方法
1. 查看模块依赖树
使用 java --list-modules
列出所有模块:
java --list-modules
# 输出示例:
java.base@17.0.1
java.sql@17.0.1
jdk.unsupported@17.0.1
2. 查看模块内容
使用 java --describe-module <模块名>
显示模块详细信息:
java --describe-module java.sql
# 输出示例:
java.sql@17.0.1
requires java.base mandated
requires java.logging transitive
requires java.xml transitive
exports java.sql
exports javax.sql
...
3.4 模块化 JDK 的优势
-
减少内存占用:
- 传统模式:加载完整的
rt.jar
(约 60 MB)。 - 模块化模式:仅加载必需模块(如
java.base
约 15 MB)。
- 传统模式:加载完整的
-
增强安全性:
- 内部 API(如
com.sun.*
)默认不可访问,避免滥用。
- 内部 API(如
-
明确依赖管理:
- 开发者必须显式声明模块依赖,避免隐式类路径问题。
3.5 实战:定制化 JRE 生成
通过 jlink
工具创建仅包含所需模块的最小化 JRE。
javabase__javasql__105">场景:构建一个仅依赖 java.base
和 java.sql
的控制台应用。
jlink --module-path $JAVA_HOME/jmods \--add-modules java.base,java.sql \--output my-custom-jre
生成的 JRE 结构:
my-custom-jre/
├── bin/
├── conf/
├── lib/ # 仅包含 java.base 和 java.sql 的模块
└── release
3.6 核心模块依赖示例
javabase__javalogging_125">示例1:依赖 java.base
和 java.logging
java">module com.myapp {requires java.logging; // 显式依赖日志模块
}
示例2:多模块协作
java">// 模块A:提供工具类
module com.utils {exports com.utils;
}// 模块B:依赖模块A和JDK的XML模块
module com.myapp {requires com.utils;requires java.xml;
}
3.7 常见问题与解决
问题 | 解决方案 |
---|---|
模块未找到(如 java.sql ) | 确认模块名拼写正确,且模块存在于 $JAVA_HOME/jmods 目录。 |
访问内部 API 失败 | 使用 --add-exports 开放访问(临时方案),或改用标准 API。 |
生成的 JRE 缺少必要模块 | 检查 jlink 的 --add-modules 参数是否包含所有依赖模块。 |
3.8 总结
JDK 9 的模块化架构通过拆分核心功能、强封装和按需加载,显著提升了 Java 应用的灵活性与安全性。开发者应熟悉核心模块(如 java.base
)的作用,掌握 jlink
等工具构建轻量化运行时,并遵循显式依赖管理原则,以充分发挥模块化优势。