jdk9变化

简介: JDK 9 引入模块化系统(JPMS),改变了类加载的双亲委派模型。关键变化包括:模块可见性优先、类加载器与模块解耦、核心类隔离及自动模块支持。新模型通过 `requires`、`exports` 和 `opens` 等机制实现更严格的访问控制,增强安全性与模块化,同时保留兼容性,使传统 JAR 可平滑过渡。

jdk9变化

关键变化点

步骤

传统双亲委派(JDK 8 及以前)

JPMS 双亲委派(JDK 9+)

可见性检查

无(仅依赖类路径)

优先检查模块间的requires

exports

opens

委派规则

无条件委派给父类加载器

受模块可见性限制,即使父类能找到类也可能拒绝加载

加载范围

类路径(classpath

)和扩展目录

模块路径(--module-path

)和自动模块

核心类隔离

依赖引导类加载器加载核心类

由模块系统强制隔离,防止非法访问核心模块

动态加载

依赖类路径和反射权限

需遵循模块的opens

reflects

规则

三、示例流程对比

场景 1:加载核心模块类(如java.lang.String

plaintext

传统流程:
应用类加载器 → 扩展类加载器 → 引导类加载器(成功加载)
JPMS流程:
1. 应用类加载器检查模块可见性:java.base模块对所有模块自动可见
2. 委派至引导类加载器(成功加载)

场景 2:跨模块加载非导出类

java

// 模块A
module a {
    exports com.example.a.public; // 仅导出public包
    // 未导出com.example.a.internal
}
// 模块B尝试加载com.example.a.internal.Class
JPMS流程:
1. 应用类加载器检查模块可见性:模块B未被授权访问a.internal
2. 即使委派至父类加载器(能找到类),仍因可见性规则拒绝加载
3. 抛出ClassNotFoundException

场景 3:加载自动模块类

java

// 自动模块legacy.jar(未声明module-info.java)
// 包含类com.legacy.LegacyClass
// 模块modern尝试加载LegacyClass
JPMS流程:
1. 应用类加载器检查模块可见性:
   - 自动模块向所有模块导出所有包
   - 模块modern隐式requires所有自动模块
2. 委派至父类加载器(未找到)
3. 应用类加载器从模块路径加载LegacyClass(成功)

四、流程图(简化版)

流程图(简化版)

plaintext

类加载请求 → [当前加载器]
           |
           ├─ 检查已加载? → 是 → 返回类
           |
           ├─ 检查模块可见性? → 否 → 抛出ClassNotFoundException
           |
           ├─ 委派给父类加载器 → [父类加载器重复上述流程]
           |
           └─ 父类加载失败 → 自身尝试加载 → 成功 → 返回类
                                       → 失败 → 抛出ClassNotFoundException

五、总结

JDK 9 的双亲委派模型通过模块可见性优先加载器与模块解耦,实现了更严格的类访问控制:


  1. 安全性增强:防止未授权模块访问其他模块的非导出类。
  2. 模块化支持:类加载与模块依赖关系紧密绑定,确保依赖一致性。
  3. 兼容性保留:通过自动模块机制支持传统 JAR 文件,平滑过渡到模块化系统。

类加载过程

相关文章
|
4月前
|
消息中间件 存储 缓存
再次了解kafka
Kafka通过offset机制解决消息重复消费问题,支持手动提交偏移量及唯一ID去重。它保证分区内的消息顺序消费,结合集群、副本与重平衡实现高可用。高性能设计包括顺序读写、分区、页缓存、零拷贝等。数据清理依赖保留时间或大小策略,点对点和发布订阅模式则通过消费者组实现。
|
4月前
|
消息中间件 NoSQL Java
延时实现
本节介绍了多种关闭过期订单的实现方案,包括定时任务、JDK延迟队列、Redis过期监听、Redisson延迟队列、RocketMQ延迟消息及RabbitMQ死信队列。各自优缺点明显,适用于不同业务场景,如定时任务适合小数据量,RocketMQ适合高并发解耦场景,而Redisson则使用简单且高效。选择时需综合考虑系统复杂度、数据量及可靠性要求。
|
4月前
|
存储 缓存 Linux
CPU上下文切换的原理及其在系统调用和进程切换中的应用
本内容深入解析了CPU上下文切换的原理及其在系统调用和进程切换中的应用。详细说明了CPU寄存器、程序计数器在任务切换中的作用,以及系统调用与进程上下文切换的区别。同时探讨了上下文切换带来的性能开销,涉及TLB和虚拟内存管理机制,帮助理解操作系统如何高效调度进程。
|
4月前
|
存储 算法 Sentinel
熔断降级
本内容介绍了微服务中熔断降级的实现原理及Sentinel的底层机制。通过OpenFeign集成Sentinel,利用断路器统计异常和慢请求比例,触发熔断并降级,提升系统稳定性。还讲解了Sentinel使用的限流算法,如滑动窗口、令牌桶和漏桶算法,以应对不同场景下的流量控制需求。
|
4月前
|
负载均衡 网络性能优化
了解EMQ
EMQ通过MQTT协议的QoS机制保障消息可靠传输,支持QoS 0、1、2三个等级,分别实现消息最多一次、至少一次和恰好一次传递。对于延迟消息,EMQ X支持通过特殊主题前缀`$delayed/{DelayInterval}`实现延迟发布。点对点通信可通过不带群组的共享订阅(如`$queue/t/1`)实现,结合负载均衡策略如随机、轮询等,确保消息仅由一个订阅者接收;发布订阅模式则通过带群组的共享订阅(如`$share/组名称/t/1`)实现,确保每组一个订阅者收取消息。
|
4月前
|
负载均衡 Java Nacos
微服务架构中的服务注册与发现流程
本内容介绍了微服务架构中的服务注册与发现流程,包括服务注册中心(如Nacos)、服务提供者和调用者的角色分工。服务启动时自动注册信息至注册中心,调用者通过客户端负载均衡(如Spring Cloud Loadbalancer)选取服务实例进行远程调用。同时,内容还讲解了OpenFeign的工作原理,其作为HTTP客户端集成负载均衡,通过接口定义、代理生成、请求发送与结果解析,实现服务间的高效通信。
|
4月前
|
存储 NoSQL 算法
Redis的集群架构与使用经验
本文介绍了Redis的集群架构与使用经验,包括主从复制、哨兵集群及Cluster分片集群的应用场景与实现原理。内容涵盖Redis主从同步机制、数据分片存储方式、事务支持及与Memcached的区别,并讨论了Redis内存用尽时的处理策略。适用于了解Redis高可用与性能优化方案。
|
4月前
|
负载均衡 Java 应用服务中间件
杂项10
Spring Cloud Alibaba 与 Spring Cloud 均基于 Spring Boot 构建微服务,遵循相同规范且组件可协同使用。区别在于,Spring Cloud Alibaba 使用 Nacos 实现服务发现与配置管理,推荐 Sentinel 作为断路器,并支持 Dubbo 与 Feign 远程调用。Nginx 可通过配置 upstream 实现负载均衡,作为反向代理,其“反向”体现在外网通过 Nginx 访问内部服务器。
|
自然语言处理 JavaScript 前端开发
使用Pagefind为VitePress文档添加离线全文搜索能力
前言 VitePress 相信大家都或多或少听说过或者用过了 默认 UI相比 VuePress2.x 好看,启动速度也快(由Vite驱动,当然VuePress也可以切换构建引擎至Vite) 做内容定制也相对简单,笔者的很多静态文档站点(使用VuePress1.x),文章内容多的时候启动非常的慢,于是就从之前的 VuePress 迁移到了 VitePress,并做了一个博客主题 @sugarat/theme => 之前也有过介绍一个简约风的VitePress博客主题 但是 VitePress 官方目前还没有内置开箱即用的搜索能力(相关PR还在施工中)
|
4月前
|
SQL NoSQL 关系型数据库
了解关系型数据库
关系型数据库基于表结构,支持SQL查询,适合复杂关系和事务处理,如Oracle、MySQL;而非关系型数据库如Redis、MongoDB采用灵活模型,适用于高并发、大数据场景。关系型数据库维护成本低但扩展性差,非关系型数据库读写快、成本低但不支持事务。索引可提升查询速度,但占用空间影响更新效率。数据库索引多采用B+树,因其更适合范围查询、磁盘读写效率高且查询性能稳定。