osgi 学习笔记一
来源:互联网 发布:java简历个人评价 编辑:程序博客网 时间:2024/05/21 10:25
浅析OSGI的bundle依赖
查看评论
Bundle是OSGI中的基础元件,不同的bundle之间可以相互依赖、引用,这样许多bundle才会共同协作,实现一些比较复杂的功能。Bundle的依赖一直是一个比较棘手的问题,包括Lazy start等,下面我们具体Bundle依赖到底是怎么一回事。
测试场景:Eclipse 3.6, Equinox
先看看基础的依赖问题
准备环境
新建2个插件,注意选择“An OSGI Framework”
新建2个基础plugin project:org.salever.osgi.depends.clientbundle、org.salever.osgi.depends.hostbundle
然后启动一个OSGI Framework,在Eclipse里面Run configuration里面,新建一个OSGI Framework:
在新建的OSGI Framework里面,仅选择新建的2个插件,然后点击add Required Bundles:
为了测试顺利,建议添加-clean参数:
如果不出意外,将会出现OSGI的控制台:
输入ss,将列举当前的bundles:
osgi> ss
Framework is launched.
id State Bundle
0
ACTIVE org.eclipse.osgi_3.
6.2
.R36x_v20110210
1
ACTIVE org.salever.osgi.depends.hostbundle_1.
0.0
.qualifier
2
ACTIVE org.salever.osgi.depends.clientbundle_1.
0.0
.qualifier
这时候仅仅有三个bundle启动,下面我们将尝试添加依赖关系,然后看看依赖关系不满足的时候,bundle的表现。
依赖
我们将尝试几种不同的场景:
- 【LAZY下】依赖不满足的时候,bundle的行为
- 正常运行的bundle,强行停止其依赖的bundles,该bundle的行为
- 无依赖的情况下,bundle的行为
在测试之前,必须先把OSGI Framework配置改下,将所有的bundle该为Lazy start,不然影响测试结果。
注意红线部分的设置。然后重启OSGI Framework。出现以下的内容,表明此时所有的bundle都是Lazy-start并且没有启动:
osgi> ss
Framework is launched.
id State Bundle
0
ACTIVE org.eclipse.osgi_3.
6.2
.R36x_v20110210
3
<<LAZY>> org.salever.osgi.depends.hostbundle_1.
0.0
.qualifier
4
<<LAZY>> org.salever.osgi.depends.clientbundle_1.
0.0
.qualifier
注意先要把Bundle都设为Lazy-start。实现Lazy-start的bundle很简单,在MANIFEST.MF中,添加
Bundle-ActivationPolicy: lazy
就可以了。
测试场景1——简单依赖
这时候修改新建的2个bundle,在org.salever.osgi.depends.clientbundle中添加对org.salever.osgi.depends.hostbundle的依赖:
保存重启OSGI Framework,然后尝试启动org.salever.osgi.depends.clientbundle
osgi> ss
Framework is launched.
id State Bundle
0
ACTIVE org.eclipse.osgi_3.
6.2
.R36x_v20110210
3
<<LAZY>> org.salever.osgi.depends.hostbundle_1.
0.0
.qualifier
5
<<LAZY>> org.salever.osgi.depends.clientbundle_1.
0.0
.qualifier
osgi> start
5
然后看看运行效果:
osgi> ss
Framework is launched.
id State Bundle
0
ACTIVE org.eclipse.osgi_3.
6.2
.R36x_v20110210
3
<<LAZY>> org.salever.osgi.depends.hostbundle_1.
0.0
.qualifier
5
ACTIVE org.salever.osgi.depends.clientbundle_1.
0.0
.qualifier
osgi>
这时候org.salever.osgi.depends.clientbundle已经启动,而依赖的bundle——org.salever.osgi.depends.hostbundle依然是
3
<<LAZY>> org.salever.osgi.depends.hostbundle_1.
0.0
.qualifier
看看clientbundle的header信息:
osgi> headers
5
Bundle headers:
Bundle-ActivationPolicy = lazy
Bundle-Activator = org.salever.osgi.depends.clientbundle.Activator
Bundle-ManifestVersion =
2
Bundle-Name = Clientbundle
Bundle-RequiredExecutionEnvironment = JavaSE-
1.6
Bundle-SymbolicName = org.salever.osgi.depends.clientbundle;singleton:=
true
Bundle-Version =
1.0
.
0
.qualifier
Import-Package = org.osgi.framework;version=
"1.3.0"
Manifest-Version =
1.0
Require-Bundle = org.salever.osgi.depends.hostbundle;bundle-version=
"1.0.0"
这时候尝试停止hostbundle:
osgi> stop
3
osgi> ss
Framework is launched.
id State Bundle
0
ACTIVE org.eclipse.osgi_3.
6.2
.R36x_v20110210
3
RESOLVED org.salever.osgi.depends.hostbundle_1.
0.0
.qualifier
5
ACTIVE org.salever.osgi.depends.clientbundle_1.
0.0
.qualifier
说明了即使被依赖的bundle不启动,clientbundle亦一样可以启动。
这里的依赖仅仅是简单的Add Required Bundle,没有使用里面的具体类,如果使用了依赖的bundle中的类了么?
测试场景2——添加具体Class调用
在hostbundle中新建类HostService:
package
org.salever.osgi.depends.hostbundle;
/**
* @author LiXP
*
*/
public
class
HostService {
public
static
void
service() {
System.out.println(HostService.
class
.toString() +
": Service"
);
}
}
然后Export这个package,使其能被其他bundle使用:
Export-Package: org.salever.osgi.depends.hostbundle
最后在clientbundle中添加使用,修改ClientActivator.java,使其在启动的时候调用
/*
* (non-Javadoc)
*
* @see
* org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext
* )
*/
public
void
start(BundleContext bundleContext)
throws
Exception {
ClientActivator.context = bundleContext;
HostService.service();
}
重启OSGI Framework,
osgi> ss
Framework is launched.
id State Bundle
0
ACTIVE org.eclipse.osgi_3.
6.2
.R36x_v20110210
1
<<LAZY>> org.salever.osgi.depends.hostbundle_1.
0.0
.qualifier
2
<<LAZY>> org.salever.osgi.depends.clientbundle_1.
0.0
.qualifier
osgi> start
2
class
org.salever.osgi.depends.hostbundle.HostService: Service
osgi> ss
Framework is launched.
id State Bundle
0
ACTIVE org.eclipse.osgi_3.
6.2
.R36x_v20110210
1
ACTIVE org.salever.osgi.depends.hostbundle_1.
0.0
.qualifier
2
ACTIVE org.salever.osgi.depends.clientbundle_1.
0.0
.qualifier
osgi>
这时候,hostbundle也启动了。这个与OSGI的lazy-start机制有关。bundle的lclass或者其它资源被Class loader装载的时候,该bundle才会启动。注意<<LAZY>>和RESOLVED 是2种状态。
测试场景3——强制停止依赖的插件
停止hostbundle:
osgi> stop
1
osgi> ss
Framework is launched.
id State Bundle
0
ACTIVE org.eclipse.osgi_3.
6.2
.R36x_v20110210
1
RESOLVED org.salever.osgi.depends.hostbundle_1.
0.0
.qualifier
2
ACTIVE org.salever.osgi.depends.clientbundle_1.
0.0
.qualifier
osgi>
clientbundle依然运行,说明在bundle已经启动以后,停止依赖的bundle,对其无影响。
依次停止2个bundle,然后启动clientbundle,看看结果:
osgi> stop
2
osgi> ss
Framework is launched.
id State Bundle
0
ACTIVE org.eclipse.osgi_3.
6.2
.R36x_v20110210
1
RESOLVED org.salever.osgi.depends.hostbundle_1.
0.0
.qualifier
2
RESOLVED org.salever.osgi.depends.clientbundle_1.
0.0
.qualifier
osgi> start
2
class
org.salever.osgi.depends.hostbundle.HostService: Service
osgi>
2个bundle都启动。
修改一下代码,看看如果clientbundle一直调用hostbundle的时候,bundle的行为:
/*
* (non-Javadoc)
*
* @see
* org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext
* )
*/
public
void
start(BundleContext bundleContext)
throws
Exception {
ClientActivator.context = bundleContext;
new
Thread(
new
Runnable() {
@Override
public
void
run() {
while
(
true
) {
HostService.service();
try
{
Thread.sleep(
5000
);
}
catch
(InterruptedException e) {
}
System.out.println(
this
.toString() +
": Sleep 5000ms"
);
}
}
}).start();
}
这里每隔5s,会发生一次调用:
osgi> org.salever.osgi.depends.clientbundle.ClientActivator$
1
@1808199
: Sleep 5000ms
class
org.salever.osgi.depends.hostbundle.HostService: Service
org.salever.osgi.depends.clientbundle.ClientActivator$
1
@1808199
: Sleep 5000ms
class
org.salever.osgi.depends.hostbundle.HostService: Service
然后停止hostbundle:
ssFramework is launched.idState Bundle0ACTIVE org.eclipse.osgi_3.6.2.R36x_v201102101RESOLVED org.salever.osgi.depends.hostbundle_1.0.0.qualifier2ACTIVE org.salever.osgi.depends.clientbundle_1.0.0.qualifierosgi> org.salever.osgi.depends.clientbundle.ClientActivator$1@1808199: Sleep 5000msclass org.salever.osgi.depends.hostbundle.HostService: Service
试试卸载hostbundle:
osgi> uninstall 1osgi> ssFramework is launched.idState Bundle0ACTIVE org.eclipse.osgi_3.6.2.R36x_v201102102ACTIVE org.salever.osgi.depends.clientbundle_1.0.0.qualifierosgi> org.salever.osgi.depends.clientbundle.ClientActivator$1@763f5d: Sleep 5000msclass org.salever.osgi.depends.hostbundle.HostService: Serviceorg.salever.osgi.depends.clientbundle.ClientActivator$1@763f5d: Sleep 5000msclass org.salever.osgi.depends.hostbundle.HostService: Serviceorg.salever.osgi.depends.clientbundle.ClientActivator$1@763f5d: Sleep 5000msclass org.salever.osgi.depends.hostbundle.HostService: Service
说明,只要bundle启动了,就算依赖的bundle没有了,它也不会受其影响。一个可能的解释为,OSGI Framework缓存了这些bundle资源。
测试场景3——依赖的插件不存在
最后我们看看,依赖的bundle不存在的时候,bundle的行为。
回到New OSGI Framework的页面,去掉org.salever.osgi.depends.hostbundle。
启动环境:
osgi> !SESSION
2012
-
04
-
05
17
:
22
:
06.432
-----------------------------------------------
eclipse.buildId=unknown
java.version=
1.6
.0_17
java.vendor=Sun Microsystems Inc.
BootLoader constants: OS=win32, ARCH=x86, WS=win32, NL=en_US
Command-line arguments: -dev file:E:/workspace/common_ws/.metadata/.plugins/org.eclipse.pde.core/New OSGI/dev.properties -os win32 -ws win32 -arch x86 -consoleLog -console -clean
!ENTRY org.eclipse.osgi
2
0
2012
-
04
-
05
17
:
22
:
07.308
!MESSAGE One or more bundles are not resolved because the following root constraints are not resolved:
!SUBENTRY
1
org.eclipse.osgi
2
0
2012
-
04
-
05
17
:
22
:
07.309
!MESSAGE Bundle initial
@reference
:file:E:/workspace/common_ws/org.salever.osgi.depends.clientbundle/ was not resolved.
!SUBENTRY
2
org.salever.osgi.depends.clientbundle
2
0
2012
-
04
-
05
17
:
22
:
07.309
!MESSAGE Missing required bundle org.salever.osgi.depends.hostbundle_1.
0.0
.
!ENTRY org.eclipse.osgi
2
0
2012
-
04
-
05
17
:
22
:
07.311
!MESSAGE The following is a complete list of bundles which are not resolved, see the prior log entry
for
the root cause
if
it exists:
!SUBENTRY
1
org.eclipse.osgi
2
0
2012
-
04
-
05
17
:
22
:
07.311
!MESSAGE Bundle org.salever.osgi.depends.clientbundle_1.
0.0
.qualifier [
1
] was not resolved.
!SUBENTRY
2
org.salever.osgi.depends.clientbundle
2
0
2012
-
04
-
05
17
:
22
:
07.312
!MESSAGE Missing required bundle org.salever.osgi.depends.hostbundle_1.
0.0
.
出现错误信息,尝试列举已有的bundle:
osgi> ss
Framework is launched.
id State Bundle
0
ACTIVE org.eclipse.osgi_3.
6.2
.R36x_v20110210
1
INSTALLED org.salever.osgi.depends.clientbundle_1.
0.0
.qualifier
bundle状态为已安装,而没有启动,尝试启动:
osgi> start
1
org.osgi.framework.BundleException: The bundle
"org.salever.osgi.depends.clientbundle_1.0.0.qualifier [1]"
could not be resolved. Reason: Missing Constraint: Require-Bundle: org.salever.osgi.depends.hostbundle; bundle-version=
"1.0.0"
at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolverError(AbstractBundle.java:
1317
)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.getResolutionFailureException(AbstractBundle.java:
1301
)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:
319
)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:
284
)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:
276
)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandProvider._start(FrameworkCommandProvider.java:
252
)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39
)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25
)
at java.lang.reflect.Method.invoke(Method.java:
597
)
at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.execute(FrameworkCommandInterpreter.java:
155
)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(FrameworkConsole.java:
156
)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.runConsole(FrameworkConsole.java:
141
)
at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(FrameworkConsole.java:
105
)
at java.lang.Thread.run(Thread.java:
619
)
这里就很好的解释了,为什么我们再运行Eclipse RCP插件时候,出现的一些类似错误的原因了。
总结
- 一般情况下,最好把bundle设为Lazy-start,这样可以节约资源,在必要的情况下,bundle会自动启用
- 如果依赖的bundle停止了,正在运行的bundle不会马上停止,仍然会继续运行
- OSGI学习笔记一
- osgi 学习笔记一
- OSGI学习笔记一(事件传递)
- OSGI笔记(一)
- OSGI笔记(一)
- OSGI学习(一)
- OSGI学习笔记
- OSGI学习笔记收藏
- OSGi 学习笔记
- osgi 学习笔记2
- osgi学习笔记
- OSGI学习笔记之OSGI框架
- OSGI笔记(一)HelloWorld
- OSGI笔记(一)HelloWorld
- OSGI笔记(一)HelloWorld
- OSGI笔记(一)HelloWorld
- maven,OSGI,karaf 学习笔记
- osgi 学习系列(一)搭建osgi platform环境
- 埋藏
- TClientDataSet和其他数据集的区别
- 人民币转成大写
- 安装Office2003提示“系统管理员设置了系统策略禁止进行此安装”
- C++监测文件夹变化
- osgi 学习笔记一
- MTU和UDP.TCP包大小的限制
- POI中设置Excel单元格格式
- 倾我万缕柔情,共你一帘幽梦
- FrameSet 调用
- Spring--quartz中cronExpression配置说明
- 打印系统整型数据极限值的C程序
- Generating an SSL certificate on Windows without IIS
- Unable to open log device '/dev/log/main' Huawai U8860 .