osgi并未颠覆双亲委派模型,而是绕过它构建细粒度、可控制、支持热插拔的类加载隔离机制:每个bundle拥有独立classloader,平级协作,依赖由框架根据manifest.mf元数据动态解析,实现双向可见性与类空间隔离。

OSGi 动态模块化架构并没有“颠覆”双亲委派模型,而是有意识地绕过它,构建了一套更细粒度、可控制、支持运行时热插拔的类加载隔离机制。
OSGi 用独立 Bundle 类加载器替代统一委托链
标准 Java 的类加载器是树状层级结构,所有应用类加载器最终都向上委托到 Bootstrap。而 OSGi 中每个 Bundle(模块)拥有自己的 ClassLoader 实例,彼此之间不构成父子委托关系,而是平级协作。Bundle A 的类加载器不会把请求交给 Bundle B 的加载器,也不会默认上抛给系统加载器——它只按自己声明的 Import-Package 和 Require-Bundle 去查找依赖,由 OSGi 框架在运行时解析并提供对应 Bundle 的导出类。
依赖解析由框架驱动,而非加载器层级决定
OSGi 把“谁能加载哪个类”的决策权从类加载器的静态继承关系,转移到了模块元数据和运行时服务注册中心:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 每个 Bundle 在 MANIFEST.MF 中明确声明
Export-Package: com.example.api和Import-Package: com.example.api; version="[1.0,2.0)" - OSGi 框架启动时构建完整的模块依赖图,确保版本兼容性与导出可见性
- 当 Bundle A 加载
com.example.api.Service时,实际调用的是框架调度后的、来自 Bundle B 的 Class 对象,而非通过父加载器层层查找
支持类加载的双向可见性与动态更新
传统双亲委派是单向向上委托,无法实现模块间受控的类共享或热替换。OSGi 则允许:
-
导出类可被多个 Bundle 同时使用,但每个 Bundle 的类空间仍相互隔离(例如各自加载的
log4j不冲突) - 卸载一个 Bundle 时,其加载的所有类可被安全回收,JVM 允许卸载满足条件的 ClassLoader 及其 Class
- 新版本 Bundle 上线后,旧版本可立即停用,新老类实例可共存过渡,无需重启 JVM
本质是“策略替换”,不是“机制破坏”
OSGi 并未重写 ClassLoader.loadClass() 来强行打破委派(如自定义加载器那样),而是让每个 Bundle ClassLoader 的 loadClass 方法直接交由框架的 PackageAdmin 或 BundleWiring 处理。它保留了类加载的基本流程,但把“从哪找类”这个关键逻辑,从硬编码的父加载器链,变成了可配置、可扩展、可动态变更的模块服务契约。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










