关于OSGI(Karaf) Classloader的几点说明

1. Java ClassLoader

Java通过Classloader加载Class,Classloader之间相互隔离。隔离真正的意思是:不同的Classloader可以加载相同的class定义,并且被jvm认定为不同的class。很多人对隔离有误解,认为不同的Classloader之间不能相互访问,这其实并不准确。可以这么理解:Classloader只是一个普通的Java类,加载的class集合是它的一个成员变量。如果一个Classloader中维护了另一个Classloader的引用,自然可以通过接口调用查找并使用另一个Classloader加载的类,双亲委派使用的正式这种机制。

双亲委派这名字乍一听好像是说你有父亲、母亲两个Classloader,你可以委派他们两个先去加载class,他们处理不了的你再处理。如果真这么理解就全错了。首先,他们不是两个,可能是n个;其次,他们不是你的父母,他们是整个jvm共享的Classloader;第三,他们谁的父母都不是,因为你和他们没有血缘(别人也没有),你不是双亲Classloader的子类。

双亲委派的英文为parent delegation,指的是每个Classloader都有一个getParent方法获取上一级的Classloader。查找类时,先调用parent Classloader查找,如果找不到在用自身的Classloader查找。层级关系如下:


parent delegation

双亲委派实际上只是引用关系,上述bootrasp、extension、application Classloader之间关系均属此类。再来看另外一张图:


自定义Classloader

bootrasp、extension、application Classloader在jvm中只有一个实例,多个用户自定义的Classloader共享此实例,完成公共部分加载。

2. OSGI Classloader

在OSGI中,每一个Bundle有一个单独的Classloader实例。更具体点,BundleWiringImpl中定义了一个BundleClassLoader,每当加载一个bundle时,框架创建一个BundleClassLoader实例负责该bundle相关class的加载工作。

BundleClassLoader的加载顺序如下:

  1. 如class在 java.* package中,委托Bootstrap Classloader处理;
  2. 如class定义在 OSGi 框架中启动委托列表(org.osgi.framework.bootdelegation)中,则将加载请求委托给Bootstrap Classloader处理;
  3. 如class在 Import-Package 定义的package中,则框架找到导出此package的 Bundle 的 Class Loader,交其处理 。
  4. 如class属于在 Require-Bundle 中定义的 Bundle,则框架找到导出此package的Bundle的ClassLoader,交其处理。
  5. Bundle 搜索自己的类资源 ( 包括 Bundle-Classpath 里面定义的类路径和属于 Bundle 的 Fragment 的类资源);
  6. 若类在 DynamicImport-Package 中定义,则开始尝试在运行环境中寻找符合条件的 Bundle 。

Bundle之间隔离,但如果存在import关系又可以委托给相应export的classloader处理。实现上无非是维护了多个import bundle的Classloader,查找时调用其find方法实现。

需要注意的是:查找时优先查找Import-Package、Require-Bundle中的类,随后才是查找Bundle自己的类。这里又引入另外一个疑问,Embed-Dependency使用问题。

简单来说,如果一个Bunlde 需要使用protobuf-java.jar,有如下两种使用方式:

  1. 普通的dependency方式使用,如下图的Component C的使用方式。
  2. Embed-dependency方式使用,如下图的ComponentA、ComponentB,此时将protobuf-java做为Bundle自身的一部分使用。
embed-dependency

按类加载的顺序,如果先加载Import-Package随后加载自身的Class,在外部存在protobuf-java,又有内嵌的protobuf-java时,如何做到使用自己的而非外部的呢?答案是在Embed-dependency中的jar并不会出现在Import-Package中。

最后再来讲一下,为什么每个bundle需要分配单独的Classloader,解决什么问题。在我看来,最主要的原因有如下两个:

  1. 定制导出类。非osgi环境下,所有package中的java类都将被导出,无法限定哪些只能jar内使用,哪些是需要export出去的。存在各种误用,耦合使用情况。
  2. 多版本控制。非osgi环境下,一个jvm对于一个类只允许存在一个版本。osgi中每个bundle是独立开发演进的,可能出现同时存在多个版本。

3. 参考资料

  1. Apache Felix Maven Bundle Plugin (BND)
  2. 类装入和调试工具介绍
  3. 探索 OSGi 框架的组件运行机制
  4. 类和类装入
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容