OSGi规范中文版(第6版 core R6.0.0)-第4章生命周期层(Life Cycle Layer)1[译]

4 生命周期层

4.1 简介

生命周期层提供了Bundle的生命周期管理API和安全控制API。生命周期层是建立在在module和安全层之上。[3]JianXiangYunKeji网站实现 (www.36lj.com)

4.1.1 要点

  • 完整性-生命周期层必须实现bundle安装、启动、停止、更新、卸载和监控状态的API。
  • 深入性-必须要提供深入到Framework实际状态的API。
  • 安全性-必须通过使用小粒度权限的方式来实现安全环境,API可以在这样的环境下使用。但是这个安全性是可选的。
  • 可管理性-必须可以使用远程方式管理OSGi framework。
  • 可启动性-必须可启动已实现了该标准的Framework的环境中。

4.1.2 术语

  • Bundle – 通常指在Framework中已安装完成的Bundle.
  • Bundle Context - bundle在Framework中的执行上下文环境。当启动或者停止一个bundle的时候,Framework将它发送到一个bundle的激活器(Bundle Activator).
  • Bundle Activator – 用于启动和停止Bundle的一个实现类.
  • Bundle Event -在Bundle内部操作生命周期的一些事件,这些事件通过Bundle Listener同步接收。
  • Framework Event – 标识Framework异常或者状态的事件,这个事件通过Framework Listener 接收。
  • Bundle Listener –监听Bundle事件.
  • Synchronous Bundle Listener – 同步方式传送Bundle Events的Listener.
  • Framework Listener – Framework事件监听器.
  • Bundle Exception – 当Framework操作失败时抛出的异常.
  • System Bundle – Framework声明或定义的Bundle.
  • Framework -framework对象实现类.允许通过External方式管理Framework.
  • Framework Factory – 创建Framework的工厂类,用于创建一个framework对象.

1

2


图4.1 Class diagram org.osgi.framework生命周期层

4.2 Framework

这节介绍launcher如何启动并管理一个framework实现,launcher并不关心framework如何实现。

4.2.1 启动、控制Framework

编码者通常希望使用一种OSGi Framework实现,这种OSGi Framework可以通过classpath或者创建指定的classloader加载代码和资源,但是怎么做到,这在规范之外。
Framework实现必须提供factory类,这个factory类可以创建出framework对象,factory类必须实现FrameworkFactory接口。Launcher能通过以下方式获取classname:

  • Service Provider Configuration model, 具体参考4.2.10 Java Service Provider Configuration Support
  • 使用Class.forName,
  • 硬编码名字.

FrameworkFactory接口只有一个方法:new Framework(Map),Map参数是framework对象的一些配置内容,这个方法返回对象为framework object(这个对象实现了Framework接口)。Framework接口继承Bunlde接口,并且增加了运行于唯一一个framework的处理方法。frameowrk object可以认为是一个系统Bundle,虽然framework object和系统Bundle不同,但是可以在不用对象中实现他们。

Framework对象被使用之前,启动器(launcher)必须通过init方法先进行初始化。在初始化完成之后,framwork对象才能提供有效的Bundle Context、注册framework service等,但是任何需要安装的Bundle必须是INSTALLED状态,这个启动器之后会配置framework对象中的安装bunlde、framework service接口以及注册启动器service。运行器能够启动Bunlde,但是这些Bundle在framework object变成ACTIVE状态之后才会被启动。

framework object配置完成后,启动器通过调用start方法启动framework,接着framework object变成ACTIVE状态,如果存在startlevel配置则修改启动级别。启动器通过waitForStop方法来控制等待framework对象停止,这是一个阻塞方法,直到framework对象完成停止并且会返回停止事件。在framework对象shutdown之后,waitForStop就会return掉,同时所有已经安装过的Bundle会变成INSTALLED状态,相同的framework重新初始化一边,多次重新尝试启动。
图4.2是一个典型的情景,一个新的framework被创建、初始化,然后launcher获得Bundle Context、安装Bunlde、启动framework、获取service、调用方法、等待framework停止等。
Figure 4.2 Action Diagram for Framework Launching

3

如果安全功能打开,启动framework时需要All权限,如果没有All权限,那么framework必须抛出SecurityException。下面的代码展示了framework如何启动:

throws Exception {
    Map p = new HashMap();
    p.put( "org.osgi.framework.storage",System.getProperty("user.home")+ File.separator+"osgi");
    FrameworkFactory factory =(FrameworkFactory) Class.forName( factoryName ).newInstance();
    Framework framework = factory.newFramework(p);
    framework.init();
    BundleContext context = framework.getBundleContext();
    for ( File bundle : bundles )
        context.installBundle( bundle.toURL().toString() );
    framework.start();
    framework.waitForStop(0);
}

4.2.2 启动期Properties

new Framework(Map)里的这个map对象提供了framework的配置属性,这个参数如果为null,那么framework会根据环境使用合理的默认值启动。例如,framework需要exportJRE的package内容作为system package,那么会将这些bundle保存到一个合适的位置中。Framework没有必要确认配置属性中的System properties以及配置属性的完整性。
配置属性内容需要是已经实现的标准属性。表4.1中的属性是所有framework需要一致实现的。

表4.1 Framework Launching Properties

Property Name

Description

org.osgi.framework.bootdelegation

指定一些Package委派给父类加载器加载,这个参数也被称为“父类委派清单”, 参考3.9.3父类委派

org.osgi.framework.bsnversion

允许或者限制安装多个相同symbolic  name的Bundle,这个属性值如下:

• single – 只允许在framework中安装一次symbolic name、version组合的Bundle,2次安装相同symbolic name、 version的Bundle是错误的

• multiple – 允许在framework中安装symbolic name相同、version不同的Bundle

• managed - (Default) 使用Bundle冲突Hook过滤非冲突bundle, 参考54 Bundle Hook Service 标准

org.osgi.framework.bundle.parent

指定boot delegation 使用的classloader。用于加载java.* 和 在org.osgi.framework.bootdelegation中指定的package.

这个属性有如下值:

• boot – 默认值,使用VM的boot class loader

• app - application class loader

• ext - extension class loader

• framework – framework的classloader

org.osgi.framework.command.execpermission

指定 an optional OS specific command to set file permissions

在bundle的native code中使用操作系统相关的命令来指定权限。这个需要使用一些操作系统的native库。示例,在 UNIX系统中可以使用如下值:

org.osgi.framework.command.execpermission="chmod +rx ${abspath}"

${abspath} 是指真实文件路径 。

org.osgi.framework.executionenvironment

以逗号分割的方式提供执行环境列表(EE). OSGi framework中必须有执行环境的所有方法。示例属性值:

CDC-1.1/Foundation-1.1,OSGi/Minimum-1.2

OSGi framework实现必须提供所有签名,这些前面定义如上述的执行环境(EE).

that are defined in the mentioned EEs. 因此,OSGi framework Server执行环境必须使用org.osgi.framework.executionenvironment属性设置所有签名.

这个属性已被废弃; 这个功能使用如下属性替代:

org.osgi.framework.system.capabilities[.extra].

org.osgi.framework.language

framework选择 native代码使用的语言,framework必须提供一个值,如果没有设置则用默认值.具体参考[7] Codes for the Representation of Names of Languages for valid values.

org.osgi.framework.library.extensions

当搜索native代码时可以使用的library文件列表,这个列表用逗号分割.如果没设置, System.mapLibraryName(String)也只会返回一个library名字. 同时允许当前操作系统设置一个或多个native库。示例,AIX允许library是.a 和.so后缀,但是 System.mapLibraryName(String) 将会只返回.a 后缀. 配置示例:

org.osgi.framework.library.extensions= a,so,dll

org.osgi.framework.os.name

在Native代码中使用的操作系统名称。如果没有设置,那么framework会提供一个默认值,表

4.3 定义了操作系统名字列表. 新的操作系统名字定义在OSGi website,具体参考[11] OSGi Reference Names. Names should be matched case insensitive.

org.osgi.framework.os.version

在native代码中使用的操作系统版本。如果没有设置,framework会提供一个默认值。标准版本语法 (e.g. 2.4.32-kwt),。launcher在启动时会校验version值。

org.osgi.framework.processor

在native代码中使用的processor名字.如果没有设置,framework必须提供一个默认值。表4.2定义了processor 名字列表. 新的processor定义在在OSGi web site, 参考[11]OSGi Reference Names. Names

should be matched case insensitive.

org.osgi.framework.security

指定framework必须使用的安全管理器类型.

如果不设置,那么framework也不会指定默认值。

以下类型已设计:

• osgi – 开启安全管理支持所有OSGi Core 安全部分标准(包括 postponed condition).

如果指定,那么security manager 需要已安装,否则当framework初始化的时候需要抛出SecurityException。

配置示例:

org.osgi.framework.security = osgi

org.osgi.framework.startlevel.beginning

指定framework中start level的开始值。具体参考Start

Level API 标准获取更详细的信息

org.osgi.framework.startlevel.beginning = 3

org.osgi.framework.storage

一个有效的文件系统路径。如果目录不存在,那么framework必须创建这个目录;如果这个目录存在,但是不是目录或者framework无法创建存储目录,那么framework初始化必须失败并且抛出异常。Framework可以自由使用这个目录,例如可以完全清楚里面的文件和目录。

如果这个值没有设置,framework必须使用一个合理的默认值。

org.osgi.framework.storage.clean

指定framework何时清理存储目录里的内容。如果没有设置,那么这个存储目录不会被清除。

合理的值如下:

• onFirstInit – 在framework bundle第1次初始化的时候清理存储目录内容

而再次初始化、启动或者更新framework bundle的时候则不会清理这个目录。

配置示例:

org.osgi.framework.storage.clean = onFirstInit

从逻辑上看应该在退出的时候删除,初始化的时候清理,然而java虚拟机并不能完全保证这个功能。

org.osgi.framework.system.capabilities

指定Provide-Capability header中的capability语法

配置值示例:

• osgi.ee

Deployer需要使用下面的属性

org.osgi.framework.system.capabilities.extra

org.osgi.framework.system.capabilities.extra

在这个属性定义的Capability都会添加到org.osgi.framework.system.capabilities属性中. 这个属性在部署的时候才被设置,语法和其他capability一样。

org.osgi.framework.system.packages

System Bundle中需要export的package.如果没有设置,那么framework需要为当前虚拟机提供一个合适的值。.

org.osgi.framework.system.packages.extra

这个属性中指定的package会被添加到org.osgi.framework.system.packages,而且语法相同。允许配置额外的只通过framework来定义package ,这个package脱离于标准虚拟机之外。

配置示例:

org.osgi.framework.system.packages.extra=org.acme.foo; version=1.2, org.acme.foo.impl

org.osgi.framework.trust.repositories

为framework指定可信任的repository。配置值为文件路径,文件路径分隔符使用File类中的pathSeparator定义,windows系统采用”,”,unix系统使用”:”。

Framework必须支持JKS类型,而且存储key,framework使用key(key中存储了合适的认证证书签名)以只读方式访问合适的repository,访问时不能有密码。

配置示例:

org.osgi.framework.trust.repositories = /var/trust/keystore.jks:~/.cert/certs.jks

org.osgi.framework.windowsystem

提供当前操作系统的名字。这个名字在native代码中使用。

可参考3.10.1 Native Code 算法。

如果没有设置,framework也需要根据当前环境设置一个合适的默认值。

表4.2Processor名称

Name

Aliases

Description

68k

Motorola 68000

ARM

Intel Strong ARM. Deprecated because it does not specify the endianness. See the following two rows.

arm_le

Intel Strong ARM Little Endian

mode

arm_be

Intel String ARM Big Endian mode

Alpha

Compaq (ex DEC)

ia64n

Hewlett Packard 32 bit

ia64w

Hewlett Packard 64 bit mode

Ignite

psc1k

PTSC

Mips

SGI

PArisc

Hewlett Packard

PowerPC

power ppc

Motorola/IBM Power PC

Sh4

Hitachi

Sparc

Sun Microsystems

Sparcv9

Sun Microsystems

S390

IBM Mainframe 31 bit

S390x

IBM Mainframe 64-bit

V850E

NEC V850E

x86

pentium i386 i486 i586 i686

Intel & AMD 32 bit

x86-64

amd64 em64t x86_64

AMD/Intel 64 bit x86 architecture

表4.3操作系统名称

Name

Aliases

Description

AIX

IBM

DigitalUnix

Compaq

Embos

Segger Embedded Software Solutions

Epoc32

SymbianOS

Symbian OS

FreeBSD

Free BSD

HPUX

hp-ux

Hewlett Packard

IRIX

Silicon Graphics

Linux

Open source

MacOS

"Mac OS"

Apple

MacOSX

"Mac OS X"

Apple

NetBSD

Open source

Netware

Novell

OpenBSD

Open source

OS2

OS/2

IBM

QNX

procnto

QNX

Solaris

Sun (almost an alias of SunOS)

SunOS

Sun Microsystems

VxWorks

WindRiver Systems

Windows95

Win95 "Windows 95" Win32

Microsoft Windows 95

Windows98

Win98 "Windows 98" Win32

Microsoft Windows 98

WindowsNT

WinNT "Windows NT" Win32

Microsoft Windows NT

WindowsCE

WinCE "Windows CE"

Microsoft Windows CE

Windows2000

Win2000 "Windows 2000" Win32

Microsoft Windows 2000

Windows2003

Win2003 "Windows 2003" Win32

"Windows Server 2003

Microsoft Windows 2003

WindowsXP

WinXP "Windows XP" Win32

Microsoft Windows XP

WindowsVista

WinVista "Windows Vista" Win32

Microsoft Windows Vista

Windows7

"Windows 7" Win32

Microsoft Windows 7

WindowsServer2008

"Windows Server 2008"

Microsoft Windows Server 2008

表4.4中的属性是framework中的固定属性,这些属性值在framework实现的时候已建立好并添加到运行属性中。如果这些属性在配置中,那么framework必须忽略他们。

表4.4ramework运行期固定属性

Property name

Description

org.osgi.framework.version

指定framework的实现版本。示例数字:1.8

org.osgi.framework.vendor

Framework的实现厂商

org.osgi.framework.uuid

Framework的唯一实例id,具体参考4.2.8 Framework UUID

org.osgi.supports.framework.extension

Framework支持扩展,需要强制性设置成true

org.osgi.supports.bootclasspath.extension

必须设置成 true 或false

org.osgi.supports.framework.fragment

Framework支持bundle片段,需要强制设置成true

org.osgi.supports.framework.requirebundle

强制支持Require Bundle,必须设置成true

所有运行期属性变量值通过getProperty(String)方法获取,具体参考4.5.3环境属性

4.2.3 Framework的生命周期

Framework一旦被创建,那么必须是INSTALL状态,在这个状态下,framework还没有成为活跃对象同时没有有效的BundleContext,从这一点上看,framework object能通过以下方法控制它的生命周期:

  • init – 如果framework对象不是active对象,那么通过这个方式改变framework对象变成STARTING状态
  • start – 确保framework在ACTIVE状态。这个方法能够在framework里调用,因为没有bundle继续running。
  • update – 停止framework.调用waitForStop返回Framework事件(STOPPED_UPDATE 或STOPPED_BOOTCLASSPATH_MODIFIED),接着重启framework到以前的状态,而运行器将使用适当的行为来再次调用waitForStop或者重启虚拟机。Update方法可以在framework或者system bundle中调用. 如果framework不是active状态,那么update是没有影响的.
  • stop – 在framework从RESOLVED状态到STOPPING状态,waitForStop方法会返回STOPPED事件。而Framework的BundleContext也不在有效,framework必须通过再次初始化来重新获取新实例以及有效的BundleContext。Stop方法可以在framework或者system bundle中调用。
  • uninstall – 绝对不能被调用,否则将会抛出Exception。

图4.3 Framework 状态图

4

4.2.4 Framework初始化

Framework在被使用之前,必须要先完成初始化。可以通过init方法或者start隐式调用来初始化。
Framework object可以被初始化多次,初始化完成之后:

  • Event handle开启
  • security manager完成配置
  • Start level设置为0
  • framework object拥有一个有效的BundleContext
  • 任何安装过的bundle都在INSTALLED或者RESOLVED状态
  • Framework service可用
  • framework状态变成STARTING
  • 有一个有效的UUID
  • system bundle能适配到任何已定义的类型中
  • 所有resolve过的扩展bundle的start方法被调用过。

4.2.4.1 启动扩展激活

Extension Bundle Activator的start方法会在framework初始化的时候被调用。
在framework初始化过程中,需要尝试resolve所有已安装过的Framework Extension。所有发生在初始化期间的resolve操作都必须只作用于system bundle和extension bundle。在framework初始化的最后一步会调用extension bundle的start方法,因此有必要在扩展Bundle被调用start方法之前,避免改变普通bundle之间的链接。而调用Extension Bundle Activator的start方法时,framework必须已经初在STARTING状态,同时有一个有效的BundleContext,Extension Bundle Activator的start方法抛出的异常类型必须是BundleException的子类。

4.2.4.2 初始化Framework的Listener

Framework初始化的时候init(FrameworkListener...)方法会被调用,同时哟一些framework listener事件。framework在初始化期间的任何广播事件都必须委托给指定的listener处理。

4.2.5 启动Framework

在framework完成初始化之后,会通过调用start方法启动,而Start方法必须是被framework实例对象调用的,start方法则改变framework的状态为ACTIVE。Framework如果没有被初始化,要启动之前也必须先初始化。

在active状态,所有已安装过的bundle需要像之前说的一样调用Bundle.start方法来启动。启动期间发生任何BundleException都会同时产生Framework Error event。如果Framework实现了Start Level规范,那么行为会不一样,具体参考Start Level API规范一节,任何已经指定active policy的bundle也必须按已有的激活策略处理,具体参考4.4.6.1 激活策略(Activation Policies)

所有进入ACTIVE状态的system bundle,会广播一个Framework STARTED事件。

4.2.6 停止Framework

Shutdown方法可以发起停止system bundle的行为,或者在framework对象中调用stop方法。framework被关闭时,首先会进入STOPPING状态,同时所有ACTIVE状态的Bundle都会被调用Bundle.stop方法。Shutdown期间发生的BundleException异常会同时产生Framework ERROR事件。Framework如果实现了Start Level规范,那么行为会不一样。

之后,framework改变start level值为0,调用Extension Bundle Activator的stop方法,停止事件句柄以及释放资源(如线程、classloader等)。然后,framework进入到RESOLVED状态并且销毁BundleContext,最后所有线程等待waitForStop方法结束。这时候如果需要重新使用Framework,那么必须重新初始化。

Framework实例对象在停止以及resolved状态后,才能被初始化和再次启动。Framework的实现必须确保重要资源不会被framework实例对象持有消耗。

4.2.6.1 停止Extension Activator

所有已经成功启动的Extension Bundle Activator的stop方法会在framework的关闭过程中调用。调用stop方法时,framework必须处在STOPPING状态并且还有有效的BundleContext,Extension Bundle Activator的stop方法抛出任何异常都回触发framework ERROR广播事件。

Framework必须保证启动的时候成功执行Extension Bundle Activator的start方法,关闭的时候必须调用BundleActivator对象的stop方法,在调用stop方法之后,BundleActivator对象绝不会再被使用。但是Extension Bundle Activator在启动过程中发生任何异常,没有必要调用shutdown方法。

4.2.7 嵌入Framework

运行器并不作为OSGi Bundle运行,而是一个普通的java应用。通常运行器需要与framework内部的bundle进行交互,而且能够使用framework实例中的BundleContext获取服务或者注册服务。然而,framework必须确保运行器对象与Bundle对象兼容,同时framework不会自动共享运行器代码和bundle之间的package,package必须显式的从父classloader导出。

org.osgi.framework.system.packages.extra这个属性设计用于application package需要在OSGi Bunlde以及application之间共享,指定的package会添加到framework的system package,system package会由system bundle显式的从父classloader导出。应该注意system package需要对加载framework的classloader可见。OSGi framework运行于多线程环境,在framework启动之后,framework会启动bundle以及这些bundle都会变成active。Active bundle会启动后台线程或者处理其他bundle的事件。在start方法return之后,framework改变状态到ACTIVE,接着所有bundle都有不同的线程运行。

Framework实例能够被framework对象中的运行器调用stop方法停止,也可以通过System Bunlde的stop方法停止。

当framework需要完全停止时,运行器通过Framework对象中的waitForStop方法进行阻塞清理,直到framework完全关闭掉,这时候在停止期间可以通过framework事件获取以下一种状态:

  • STOPPED – 表示framework对象已经关闭,同时framework能够重启。
  • STOPPED_UPDATE – 表示framework对象已经被更新,将要进行重启,在完成重启之前,framework的状态是ACTIVE或者STARTING。
  • STOPPED_BOOTCLASSPATH_MODIFIED – framework实例已经被停止,因为boot class path extension bundle 已经installed或者updated。虚拟机受影响必须按顺序改变boot classpath。
  • ERROR – 在framework关闭期间发生了异常。
  • WAIT_TIMEDOUT – 表示方法执行超时,framework被完全停止之前提前被return了。

4.2.8 Framework UUID

每个framework在启动后都必须有一个唯一的身份,这个身份在framework属性中:

org.osgi.framework.uuid

这个属性值必须是string类型,这个值在[14] IETF RFC 1422 A Universally Unique
IDentifier (UUID) URN Namespace with the urn:uuid: prefix中有定义,uuid值示例:

f81d4fae-7dec-11d0-a765-00a0c91e6bf6

java的UUID类虽然具有自己生成UUID的能力,然而,framework却会通过其他方式自己创建一个全局的uuid,即使在配置中指定了这个属性,framework也必须重写这个值。

4.2.9 守护线程(Daemon Thread)

当只有守护线程运行的情况下,java虚拟机将会自动退出。当framework只使用守护线程以及所有通过bundle创建的守护线程时,就创建出了一个允许VM退出的环境。因此在有active bundle的情况下,framework必须确保VM不能退出,实现方式之一就是一直都有一个非守护线程保持活跃即可。

4.2.10 Java Service Provider配置支持

Java Service Provider Configuration模型定义在[13] Java Service Provider Configuration中,一种方式是从JAR的resource中读取,在这个规范中,假设framework实现从classpath中读取配置信息,如META-INF/services/org.osgi.framework.launch.FrameworkFactory。
配置示例:
META-INF/services/org.osgi.framework.launch.FrameworkFactory里的文本内容为

# ACME Impl. for OSGi framework
com.acme.osgi.Factory

Java 6提供了java.util.ServiceLoader类来方便的加载这种factory类,实例实现代码如下:

ServiceLoader<FrameworkFactory> sl =ServiceLoader.load(FrameworkFactory.class);
Iterator<FrameworkFactory> it = sl.iterator();
if ( it.hasNext() ) {
    Framework fw = it.next().newFramework(null);
    ...
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值