`
snoopy7713
  • 浏览: 1140396 次
  • 性别: Icon_minigender_2
  • 来自: 火星郊区
博客专栏
Group-logo
OSGi
浏览量:0
社区版块
存档分类
最新评论

Equinox加载Bundle Class的实现

    博客分类:
  • OSGi
阅读更多

Equinox 在创建 Bundle ClassLoader 时,首先获取 bundle classpath ,然后执行 createBCLPrevileged 方法,此方法最后转交由 BaseData 来创建 ClassLoader

BaseDate创建ClassLoader的关键代码片段为:


在Equinox中,默认的情况下adaptor.getBundleClassLoaderParent返回的为bootstrap  classloader,可通过修改启动的osgi.parentClassLoader  来改变这个parent classloader,

osgi.parentClassLoader 的可选值有四个,分别是:

boot                  :    默认

app        :    SystemClassLoader

ext             :     SystemClassLoader parent

fwk            :     启动 Equinox ClassLoader

ClassLoadingHook在createClassLoader的时候都没有做动作,因此最后ClassLoader都是通过创建 DefaultClassLoader对象来构建的,其中parent参数为null,delegate参数为BundleLoader实 例,bundleclasspath参数为bundle的classpath。

经过以上步骤后,完成了ClassLoader的创建,可以开始加载class了,根据上面上述,Bundle的Class就由DefaultClassLoader来完成了。

查看DefaultClassLoader的loadClass代码,发现真正的加载class的过程是转为调用了delegate 的 findClass来完成的,delegate参数对应的为BundleLoader实例,转为跟踪BundleLoader的findClass方法。

BundleLoader的findClass方法的代码片段:


从以上这个代码片段,可以看到,Equinox将java.开头的类转交给了parent classloader去加载,这也意味着没必要在系统中提供对外export java.开头的package。

如果不是java.开头的类,则交由findClassInternal方法来完成加载。

findClassInternal方法遵循的为OSGi规范中定义的Class的加载顺序,不过仍然稍有改动:

 

1)          判断是否交由 parent classloader 去完成加载

在启动Equinox时,Equinox会读取org.osgi.framework.bootdelegation属性,该属性对应配置的为需要 从parent classloader中加载的package,如值配置的为*,说明所有的都从parent classloader中加载 ,如值配置的为具体的package,那么则放入bootDelegation集合;如配置的为带通配符的 package,那么则放入bootDelegationStems集合。

判断时Equinox首先判断是否所有的都从parent classloader中加载,如是则从parent classloader中加载;

如需要加载的类的package位于bootDelegation或bootDelegationStems集合中,那么同样从parent classloader中加载。

如不从parent classloader中加载,则进入下面的步骤。

2)          尝试调用 Equinox 提供的 ClassLoaderDelegateHook 的扩展来加载

Equinox对外提供了ClassLoaderDelegateHook的接口扩展,可编写ClassLoaderDelegateHook的实现,注册到Framework中,那么当有Class需要加载等动作时都会得到通知。

在默认情况下,Equinox中没有ClassLoaderDelegateHook的实现,因此继续下面的步骤。

3)          判断是否在 import-package 中,如在则交由相应的 PackageSource 去加载

根据Bundle配置的import-package,判断目前需要加载的类是否在import-package中,如在则交由对应的 PackageSource进行加载,PackageSource在加载时即直接交由对应的Bundle的classloader去加载,如加载的类的 package在import-package中,但加载后仍然没有找到Class,则直接抛出ClassNotFoundException,如加载 到,则直接返回。

如所需要加载的类的package不在import-package中,则继续下面的步骤。

4)          尝试从 require-bundle 中加载

尝试使用require-bundle来加载,如加载到,则直接返回,如加载不到,则继续下面的步骤。

5)          尝试从当前 Bundle 中加载

直到经过以上步骤的尝试,才尝试由当前Bundle中加载,当前Bundle加载的方法即从Bundle-Classpath或当前Bundle的 Fragment中查找相应名称的class文件,并读取该文件进行加载,如class文件已加载,则进行缓存,再次加载时则不需要查找和解析class 文件。

如从当前Bundle中仍然未找到所需的类,则继续下面的步骤。

6)          尝试从 DynamicImport-Package 中加载

判断需要找的类的package是否在DynamicImport-Package中,如果在,则交由相应的PackageSource进行加载, 如PackageSource中加载不到,则抛出ClassNotFoundException;如不在DynamicImport-Package中, 则继续下面的步骤。

7)          再次尝试调用 Equinox 提供的 ClassLoaderDelegateHook 的扩展来加载

这步和第2)步相同,因此在默认情况下继续下面的步骤。

8)          尝试使用 eclipse buddy 机制来加载

Buddy机制是Eclipse的扩展,并不符合OSGi规范,因此在此不做深入分析。

9)          判断一定的条件,如符合则从 parent classloader 中加载

判断的条件为:parent classloader不为null、不从parent classloader中加载、Equinox的向后兼容属性(osgi.compatibility.bootdelegation)为true以及 jvm的bug class,如满足以上条件,则尝试从parent classloader中加载。

如经过以上所有步骤后,仍然未找到需要加载的class,则抛出ClassNotFoundException。

从上面的代码分析 中,在Equinox中可以通过osgi.parentClassLoader、org.osgi.framework.bootdelegation来 控制从Bundle ClassLoader外来加载Class,这对于集成Equinox其他容器而言,非常有用,另外,还可以通过实现 ClassLoaderDelegateHook来改变Class的加载。


  • 大小: 146.7 KB
  • 大小: 27.3 KB
  • 大小: 146.7 KB
  • 大小: 9.1 KB
  • 大小: 65.6 KB
分享到:
评论

相关推荐

    使用Equinox开发OSGI应用程序工程及源码

    每个OSGi模块(Bundle)都是一个独立的JAR文件,有自己的类加载器,遵循特定的MANIFEST.MF规范。 2. **Equinox环境搭建**:首先,需要安装Eclipse IDE,然后通过Eclipse的插件管理器安装OSGi开发所需的Equinox SDK...

    ‪第一个OSGi框架工程

    OSGi提供了一套API用于操作这些状态,使得开发者可以在程序运行时动态地加载或卸载Bundle,从而实现系统的灵活性和扩展性。例如,使用`start`和`stop`命令可以轻松地控制Bundle的状态。 **服务层(Service Layer)*...

    java调用插件代码.rar

    通过`Class`类的`forName()`方法加载类,然后使用`newInstance()`创建对象,或者通过`getMethod()`和`invoke()`执行特定方法。 2. **Java Service Provider Interface (SPI)**: Java SPI是一种用于服务发现和加载...

    乱凑的一个osgi的demo

    - `target`或`build`:构建输出目录,可能包含编译后的class文件和打包好的bundle JAR 要深入理解并运行这个OSGi demo,你需要: 1. 安装合适的OSGi运行时环境,如Apache Felix或Eclipse Equinox。 2. 解压`app01`...

    OSGi崁入Servlet的配置步驟

    它们都实现了OSGi服务规范,提供了Servlet 3.0或更高版本的支持,使得可以直接在OSGi Bundle中注册Servlet。 3. **创建OSGi Bundle** 使用Maven或Gradle等构建工具,创建一个新的OSGi Bundle项目。确保在pom.xml或...

    OSGI入门和整合Spring

    通过以上步骤,我们不仅实现了 OSGi Bundle 的基本功能,还成功地将 Spring 框架集成到了 Bundle 中。这样的整合使得 Bundle 能够更好地利用 Spring 的特性,如依赖注入和面向切面编程,从而构建更加灵活、可扩展的...

    高薪面试题 java

    - **类加载机制**:每个bundle有自己的类加载器,通过特定机制加载其他bundle中的类。 #### JVM调优实践 - **调优工具**:如VisualVM、JProfiler等。 - **案例分析**:例如通过监控发现频繁的Full GC导致性能瓶颈,...

    Spring OSGi 入门.pdf

    - **额外的Bundle**:在测试运行时,还需要启用特定的Bundle,如`jcl104.over.slf4j`、`org.eclipse.equinox.http`等。 #### 三、Spring-DM Bundle配置 Spring-DM Bundle的配置主要包括以下几个方面: 1. **`...

    spring osgi 入门

    在Spring-DM Bundle中,可以在`META-INF/spring/`目录下放置Spring配置文件,所有位于该目录下的XML文件都会被默认加载。 **示例配置**: ```xml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:...

    osgi-jetty-9.3.10环境配置-注册Servlet工程示例

    OSGi(Open Services Gateway Initiative)是一种模块化系统和Java服务框架,它允许应用程序按需加载和卸载组件,实现动态的、可插拔的架构。Jetty是一款轻量级、高性能的HTTP服务器和Servlet容器,它能够直接在OSGi...

    spring-dm junit

    在这些类中,你可以使用`@RunWith(SpringJUnit4ClassRunner.class)`注解来表明测试需要Spring Test的支持。 3. **定义测试上下文**:使用`@ContextConfiguration`注解来指定包含被测试组件的Spring配置文件。这样,...

Global site tag (gtag.js) - Google Analytics