OSGi™ 是 Java 上的动态模块系统。它为开发人员提供了面向服务和基于组件的运行环境,并提供标准的方式用来管理软件的生命周期。OSGi 已经被实现和部署在很多产品上,在开源社区也得到了广泛的支持。Eclipse 就是基于 OSGi 技术来构建的。
OSGi 中的每个模块(bundle)都包含 Java 包和类。模块可以声明它所依赖的需要导入(import)的其它模块的 Java 包和类(通过 Import-Package),也可以声明导出(export)自己的包和类,供其它模块使用(通过 Export-Package)。也就是说需要能够隐藏和共享一个模块中的某些 Java 包和类。这是通过 OSGi 特有的类加载器机制来实现的。OSGi 中的每个模块都有对应的一个类加载器。它负责加载模块自己包含的 Java 包和类。当它需要加载 Java 核心库的类时(以 java 开头的包和类),它会代理给父类加载器(通常是启动类加载器)来完成。当它需要加载所导入的 Java 类时,它会代理给导出此 Java 类的模块来完成加载。模块也可以显式的声明某些 Java 包和类,必须由父类加载器来加载。只需要设置系统属性 org.osgi.framework.bootdelegation 的值即可。
假设有两个模块 bundleA 和 bundleB,它们都有自己对应的类加载器 classLoaderA 和 classLoaderB。在 bundleA 中包含类 com.bundleA.Sample,并且该类被声明为导出的,也就是说可以被其它模块所使用的。bundleB 声明了导入 bundleA 提供的类 com.bundleA.Sample,并包含一个类 com.bundleB.NewSample 继承自 com.bundleA.Sample。在 bundleB 启动的时候,其类加载器 classLoaderB 需要加载类 com.bundleB.NewSample,进而需要加载类 com.bundleA.Sample。由于 bundleB 声明了类 com.bundleA.Sample 是导入的,classLoaderB 把加载类 com.bundleA.Sample 的工作代理给导出该类的 bundleA 的类加载器 classLoaderA。classLoaderA 在其模块内部查找类 com.bundleA.Sample 并定义它,所得到的类 com.bundleA.Sample 实例就可以被所有声明导入了此类的模块使用。对于以 java 开头的类,都是由父类加载器来加载的。如果声明了系统属性 org.osgi.framework.bootdelegation=com.example.core.*,那么对于包 com.example.core 中的类,都是由父类加载器来完成的。
OSGi 模块的这种类加载器结构,使得一个类的不同版本可以共存在 Java 虚拟机中,带来了很大的灵活性。不过它的这种不同,也会给开发人员带来一些麻烦,尤其当模块需要使用第三方提供的库的时候。下面提供几条比较好的建议:
•如果一个类库只有一个模块使用,把该类库的 jar 包放在模块中,在 Bundle-ClassPath 中指明即可。
•如果一个类库被多个模块共用,可以为这个类库单独的创建一个模块,把其它模块需要用到的 Java 包声明为导出的。其它模块声明导入这些类。
•如果类库提供了 SPI 接口,并且利用线程上下文类加载器来加载 SPI 实现的 Java 类,有可能会找不到 Java 类。如果出现了 NoClassDefFoundError 异常,首先检查当前线程的上下文类加载器是否正确。通过 Thread.currentThread().getContextClassLoader() 就可以得到该类加载器。该类加载器应该是该模块对应的类加载器。如果不是的话,可以首先通过 class.getClassLoader() 来得到模块对应的类加载器,再通过 Thread.currentThread().setContextClassLoader() 来设置当前线程的上下文类加载器。
稍微记录一下。
转自:成 富, 软件工程师, IBM 中国软件开发中心 文章
分享到:
相关推荐
JVM、OSGI(Open Service Gateway Initiative)和Tomcat等容器都涉及到了类加载器的概念,理解它们的工作原理对优化应用性能和解决依赖冲突至关重要。 1. JVM类加载器: - **父类加载器**:在Java中,类加载器之间...
6. 类加载器与异常: 在类加载过程中,可能会遇到`ClassNotFoundException`和`NoClassDefFoundError`等异常。前者通常是因为类加载器无法找到指定的类,后者则可能发生在类已被加载但无法找到其定义的情况下。 7. ...
类加载器是 Java 语言的一个创新,也是 ...不过如果遇到了需要与类加载器进行交互的情况,而对类加载器的机制又不是很了解的话,就很容易花大量的时间去调试 ClassNotFoundException和 NoClassDefFoundError等异常。
每个线程都有一个与之关联的类加载器,可以通过Thread.currentThread().getContextClassLoader()获取。这在某些情况下非常有用,例如在Web应用服务器中加载特定Web应用的类。 在Web容器(如Tomcat)中,每个Web应用...
类加载器是 Java 语言的一个创新,也是 ...不过如果遇到了需要与类加载器进行交互的情况,而对类加载器的机制又不是很了解的话,就很容易花大量的时间去调试 ClassNotFoundException和 NoClassDefFoundError等异常。
- **OSGi**:OSGi是一个Java平台的模块化框架,它通过类加载器机制实现了严格的模块化隔离,使得不同的模块之间可以动态加载、卸载以及更新,极大地提高了系统的灵活性和可维护性。 #### 结论 类加载器是Java生态...
OSGI提供了一个运行时环境,允许Java应用被部署到一个或者多个分布式服务器上,而类加载器在这样的环境下扮演着核心角色。 总的来说,类加载器和类加载机制是Java语言动态性的基础,了解它们的工作原理不仅有助于...
除了这三种预定义的类加载器,Java还提供了一种特殊的**线程上下文类加载器(Thread Context ClassLoader)**,它允许在特定线程中加载类时使用非默认的类加载器。这在插件框架和OSGi等动态部署环境中尤其有用。 ...
2. OSGi的ClassLoader支持动态加载和卸载bundle,当bundle被激活或停用时,对应的类加载器可以按需加载或释放类,提高了系统的灵活性和可维护性。 3. OSGi的ClassLoader还支持类的重用,如果两个bundle引用了相同的...
例如,使用 OSGi(Open Service Gateway Initiative)框架,就可以管理多个模块化应用的生命周期,每个模块有自己的类加载器,允许动态安装、卸载和更新。 1.5 常见问题分析 类加载过程中可能会遇到一些问题,如类...
2. **类加载器调整**:由于Tomcat和OSGI都有自己的类加载机制,整合时需要调整Tomcat的类加载策略,以兼容OSGI的模块化特性。这可能涉及创建一个新的类加载器,用于加载OSGI Bundle内的类。 3. **配置管理**:OSGI...
4. **类加载器**:每个bundle有自己的类加载器,负责加载bundle内的类,避免类冲突。 5. **Repository**:存储bundle信息的地方,bundle可以从其中获取依赖的bundle。 ### OSGi的应用场景: 1. **嵌入式系统**:...
这些错误往往与类加载器的工作方式以及类的加载顺序有关。 6. **自定义类加载器**: 开发者在需要动态加载类,比如热部署、插件系统或隔离不同版本的库时,可能会编写自定义类加载器。自定义加载器需要重写`load...
1. 模块系统:OSGi的核心是其模块系统,它基于Java类加载器的增强,使得每个模块(Bundle)都有自己的类加载器。这样,不同模块之间可以有明确的依赖关系,避免了类冲突问题。 2. 动态性:OSGi环境支持模块的动态...
3. **类加载器**:OSGI使用类加载器的层次结构来处理不同Bundle间的类加载,确保每个Bundle有自己的类加载器,避免类冲突。 4. **服务注册与查找**:通过OSGI服务注册表,模块可以注册服务供其他模块使用,也可以...
1. **模块化**:OSGi通过定义严格的类加载器层次结构,实现了模块间的隔离。每个bundle都有自己的类加载器,避免了类冲突,使得多个版本的相同库可以并存。 2. **动态性**:OSGi支持动态部署和更新,允许在运行时...
每个bundle都有自己的类加载器,确保了不同bundle之间的类隔离。生命周期管理则涉及bundle的启动、暂停、停止和卸载操作,使开发者可以控制服务的动态性。服务注册与发现机制则通过服务事件和服务引用实现组件间的...
2. **类加载器机制**:OSGI引入了一种层次化的类加载器结构,每个服务单元有自己的类加载器,可以控制对类的访问,实现类的隔离。这使得一个服务单元中的类只对自己可见,除非明确导出给其他服务单元。 3. **依赖...
为了解决这个问题,OSGi引入了模块化概念,每个模块(称为bundle)都有自己的类加载器,可以在同一环境中并行运行不同版本的库。 在"myself"工程中,我们创建了两个不同版本的“myself”jar包。每个jar包都包含了...
1. **类加载器问题**:OSGi的类加载机制可能导致类的可见性问题,尤其是在涉及AOP代理时。同一类可能由不同的bundle加载,这可能导致事务无法正常工作,因为Spring的代理可能无法正确识别到目标类。 2. **...