OSGi类加载流程
思路
OSGi每个模块都有自己独立的classpath。如何实现这一点呢?是因为OSGi采取了不同的类加载机制:
- OSGi为每个bundle提供一个类加载器,该加载器能够看到bundle Jar文件内部的类和资源;
- 为了让bundle能互相协作,可以基于依赖关系,从一个bundle类加载器委托到另一个bundle类加载器。
Java和J2EE的类加载模型都是层次化的,只能委托给上一层类加载器;
而OSGi类加载模型则是网络图状的,可以在bundle间互相委托。——这样更合理,因为bundle间的依赖关系并不是层次化的。
- 例如bundleA、B都依赖于bundleC,当他们访问bundleC中的类时,就会委托给bundleC的类加载器,由它来查找类;如果它发现还要依赖bundleE中的类,就会再委托给bundleE的类加载器。
优点
- 找不到类时的错误提示更友好。假如bundleE不存在,则bundleC就不会被解析成功,会有错误消息提示为何未能解析;而不是报错ClassNotFoundException或NoClassDefFoundError。
- 效率更高。在标准Java类加载模型中,总是会在classpath那一长串列表中进行查找;而OSGi类加载器能立即知道去哪里找类。
类加载步骤
Step 1: 检查是否java.*,或者在bootdelegation中定义
当bundle类加载器需要加载一个类时,首先检查包名是否以java.*开头,或者是否在一个特定的配置文件(org.osgi.framework.bootdelegation)中定义。如果是,则bundle类加载器立即委托给父类加载器(通常是Application类加载器)。
这么做有两个原因:
- 唯一能够定义java.*包的类加载器是bootstrap类加载器,这个规则是JVM要求的。如果OSGI bundle类加载器试图加载这种类,则会抛Security Exception。
- 一些JVM错误地假设父加载器委托永远会发生,内部VM类就能够通过任何类加载器找到特定的其他内部类。所以OSGi提供了org.osgi.framework.bootdelegation属性,允许对特定的包(即那些内部VM类)使用父加载器委托。
Step 2: 检查是否在Import-Package中声明
Step 3: 检查是否在Require-Bundle中声明
Step 4: 检查是否bundle内部类
检查是否是该bundle内部的类,即当前JAR文件中的类。
Step5: 检查fragment
搜索可能附加在当前bundle上的fragment中的内部类。
什么是fragment?
Fragment bundle是OSGi 4引入的概念,它是一种不完整的bundle,必须要附加到一个host bundle上才能工作;fragment能够为host bundle添加类或资源,在运行时,fragment中的类会合并到host bundle的内部classpath中。
fragment有什么作用?
【场景1】bundle中有针对特定平台的代码
假设bundle对不同平台的实现方式稍有不同,Windows和Linux下代码有不同之处,即bundle中有针对特定平台的代码。
我们应该为每个平台提供不同的bundle吗?——显然不能,因为那会造成代码重复。
或者将共同代码放到bundle A中,Windows特定的那部分代码放到bundle Pwin中,Linux特定的那部分代码放到bundle Plinux中。——有问题:Pwin肯定要依赖A中某些包,我们就必须在A中导出这些包,如果只有Pwin用到这些包 岂不破坏封装性。
最好的解决方法是把Pwin作为fragment,附加到A中。这样Pwin就能看到A中的所有包,A也能看到Pwin的所有包。
【场景2】针对不同国家用户提供不同的i18n
GUI程序通常会通过properties文件定义i18n信息,可以将不同的i18n存到不同的fragment中。运行时用户只需要下载host bundle以及特定的i18n fragment即可,不需要把其他国家的i18n也下载下来。
Step6: 动态类加载
//TODO
完整的类加载流程图如下:
OSGi类加载流程的更多相关文章
- OSGi类加载问题
项目中遇到的JVM难点 ——启动OSGi容器时,出现永久代内存不够.内存泄露 ——OSGi找不到类路径问题. ——线程死锁问题. 问题一:OSGi类内存问题 其次,从内存用量来看, ...
- JVM,Tomcat与OSGi类加载机制比较
首先一个思维导图来看下Tomcat的类加载机制和JVM类加载机制的过程 类加载 在JVM中并不是一次性把所有的文件都加载到,而是一步一步的,按照需要来加载. 比如JVM启动时,会通过不同的类加载器加载 ...
- 并行类加载与OSGI类加载
这回来分析一下OSGI的类加载机制. 先说一下OSGI能解决什么问题吧. 记得在上家公司的时候,经常参与上线.上线一般都是增加了一些功能或者修改了一些功能,然后将所有的代码重新部署.过程中要将之前的服 ...
- Android类加载流程
背景 由于前前前阵子写了个壳,得去了解类的加载流程,当时记了一些潦草的笔记.这几天把这些东西简单梳理了一下,本文分析的代码基于Android8.1.0源码. 流程分析 从loadClass开始,我们来 ...
- JVM类加载流程
1.加载 a.装载类的第一个阶段 b.取得类的二进制流 c.转为方法区数据结构 d.在Java堆中生成对应的java.lang.Class对象 2.链接 a.验证(保证Class流的格式是正确的) 文 ...
- 深入理解JVM(六)——类加载器原理
我们知道我们编写的java代码,会经过编译器编译成字节码文件(class文件),再把字节码文件装载到JVM中,映射到各个内存区域中,我们的程序就可以在内存中运行了.那么字节码文件是怎样装载到JVM中的 ...
- JVM学习--(六)类加载器原理
我们知道我们编写的java代码,会经过编译器编译成字节码文件(class文件),再把字节码文件装载到JVM中,映射到各个内存区域中,我们的程序就可以在内存中运行了.那么字节码文件是怎样装载到JVM中的 ...
- 深入理解JVM一类加载器原理
我们知道我们编写的java代码,会经过编译器编译成字节码文件(class文件),再把字节码文件装载到JVM中,映射到各个内存区域中,我们的程序就可以在内存中运行了.那么字节码文件是怎样装载到JVM中的 ...
- 深入理解JVM虚拟机6:深入理解JVM类加载机制
深入理解JVM类加载机制 简述:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 下面我们具体 ...
随机推荐
- Thymleaf 从某处(不包含某处)开始截取字符串到末尾
简单描述:数据库存放的是id+name,但是做展示的时候,只需要展示name,不展示id.不管是在前台还是在后台,使用传统的方法截取,也是可以的,但是thymleaf提供了一种截取字符串,可以实现从某 ...
- Jenkins通过git tags进行回滚代码
配置Jenkins获取git tag代码的方式其实方法很多,目前我使用比较多的主要是通过Git Parameter 来配置动态的获取最新tags代码,主要我们首先需要安装一下Git Parameter ...
- layui报错 "Layui hint: 模块名 xxx 已被占用" 的问题解决方案
由于扩展模块数量众多, 于是我需要将扩展模块分类到二级文件夹中, 我在页面中是这么写的 <script> layui.extend({ courseTask: 'task/courseTa ...
- .Net core使用Autofac进行依赖注入示例
一.官方文档 https://autofaccn.readthedocs.io/zh/latest/index.html 二.新建.net core 控制台程序 三.注册类型,示例一 1.新建接口 I ...
- Win10 iot 修改日期时间
发现树莓派的日期是错的 iot 下可以使用 Set-Date 来设置日期和时间 文档:https://docs.microsoft.com/en-us/previous-versions/window ...
- linux上部署JMeter
export JAVA_HOME=/opt/jdk1.8.0_171 export PATH=$PATH:$JAVA_HOME/bin 让环境变量生效 vi /etc/profile 添加下述两行: ...
- 将source类中的属性值赋给target类中对应的属性
/** * 对象的属性值拷贝 * <p> * 将source对象中的属性值赋值到target对象中的属性,属性名一样,类型一样 * <p> * example: * <p ...
- 什么是HTTP及RFC
HTTP:超文本传输协议(HyperText Transfer Protocol),是互联网上应用最为广泛的一种网络协议. 所有的www文件都必须遵守这个标准.设计HTTP最初的目的是为了提供发布 ...
- ./graldew bash: ./gradlew: No such file or directory
使用gradlew的项目,可以使用./gradlew assembelDebug 使用本地gradle编译的项目,并且配置了环境变量,可以使用gradle assembleDebug直接编译包
- [R]R语言的module工程化
很遗憾,这还是一个挖坑的问题,解决方案并不是很确定. 需求是,大多数的语言都提供import包或module的功能,避免全部代码写到一个文件中,方便管理与维护. 如常用的database模块,每次写R ...