第29卷第2期 2012年2月 计算机应用与软件 Computer Applications and Software Vo1.29 NO.2 Feb.20l2
一种面向方面的软件容错能力增强工具
黄焱艺 于 阳 彭 鑫赵文耘 (复旦大学计算机科学技术学院上海200433) 摘 要 容错是保障软件可靠性的重要手段。该目标是利用对软件系统静态分析的信息,生成具有客错能力的方面文件来增强 软件系统的容错能力。首先利用抽象语法树的分析工具,来获得一些有用信息,比如异常类型和抛出异常的方法。然后通过模板生 成工具生成相应的恢复代码,利用面向方面机制,将代码动态编织入系统中。最后做一个案例证明方法在实现容错增强方面的可 行性。 关键词 软件容错 中图分类号TP317 面向方面 工具 文献标识码A
AN ASPECT.oRIENTED SoFTWARE FAULT ToLERANCE ENHANCEMENT TOoL
Huang Yanyi Yu Yang Peng Xin Zhao Wenyun (School ofComputer Science,Fudan Un#e ̄ity,Shanghai 200433,China) Abstract Fault tolerance is an important means to assure software reliability.The goal of this paper is to use the infommtion of static analysis on software system to form the aspect file with fault tolerance capability for enhancing the fault tolerance capability of software system. We first use the analysis tool of abstract syntax tree to get some useful information,such as the type of exception and the method of exception throwing.Then we use template generation tool to generate corresponding recovery code,and use aspect—oriented mechanism to weave the code into the system dynamically.Finally,we make a case to prove the feasibility of the method in realising fault tolerance enhancement. Keywords Fault.・tolerance of software Aspect・-oriented Tool
0 引 言 软件系统正越来越多的应用到生活的方方面面,但是开发 一个没有缺陷的软件系统通常是非常困难的,因此软件有时会 失效,失效的后果可能只是造成一些不方便(比如电视机遥控 器不能用),也可能是灾难性的(比如商业飞机上的软件故 障)…。为了使软件系统在出现失效时能够继续运行,提出了 容错技术,容错是保障软件可靠性的重要方式。文献[2]讲述 了一些当前的容错技术,包括恢复块,N版本编程等。异常处理 是构建高可靠性容错系统的一个重要方面。异常处理最早是由 John Goodenough在1975年在文献[3]中提出来的。现在异常 通常都被定义为在程序执行过程中影响程序正确行为的特殊事 件。程序语言的设计者经常忽略异常机制,这就让开发异常处 理代码的开发者觉得开发一个好的异常处理代码是困难的,容 易出错的,而且效率不高。并且,对异常处理不完美的程序来 说,当程序出现异常,系统就会停止运行,极大影响了程序可靠 性和用户体验,所以异常处理在高可靠系统的实现中有着重要 的作用。 本文给出一个工具,该工具通过对抽象语法树静态分析的 信息来定位异常和判定异常信息,由此选择异常恢复策略,结合 AOP技术,工具实现自动生成异常捕获代码,生成AspeetJ程序 模板,并且通过分析代码定义了常见异常的通用处理模式,同时 支持用户自定义异常处理方式。 1背景介绍
Java的异常处理机制包含三部分:Throws说明可能抛出的 异常,调用该方法必须处理这些事件;将可能抛出异常的代码放 在try块中,处理放在catch块中,finally用于恢复系统状态; Throw后面跟异常对象类型,说明抛出的异常。对于Java异常 可分为检查异常和未检查异常。本文主要处理检查异常。文献 [4]中研究表明,程序员并不常书写代码处理异常,更多时候是 采取忽略或者简单返回一个缺省值并终止程序的方式来处理, 而不是真正的去规划恢复策略,书写恢复代码。而很多时候对 异常恢复策略的规划是有意义的。由于异常处理可能引发的控 制流复杂性和异常本身的复杂性,比如即使是同一个异常,处理 策略也经常是各不相同的,这就给异常处理策略的规划增加了 难度。 由于异常分布的散乱性,直接在系统中书写异常代码会和 已有代码交缠在一起,因而在异常处理中引入面向方面的思想 是有意义的。面向方面的编程是面向对象编程的有效补充,提 供了新的语言特性来增强模块化和分离关注点,可以以非侵入 方式改变程序的执行方式,极大地降低了异常处理代码和原代
收稿13期:2011—05一O7。国家自然科学基金(90818009)。黄焱
艺,硕士,主研领域:软件容错自适当。 10 计算机应用与软件 2012血
码的耦合性 J。但是面向方面能否增加系统的模块化仍然是 一个值得探讨的问题。文献[6]中指出,如果异常处理代码很 大程度上是上下文相关的,那么使用面向方面技术带来的好处 就有限,但是如果能事先规划好,面向方面会是一个很好的补 充。所以本文通过工具提供了自动的代码生成,同时也提供了 一定的灵活性,与上下文相关的内容,我们允许开发者自己定 义。通过自定义的代码生成工具生成方面文件,对已有的程序 进行打补丁式的补充,增强了程序的异常处理和容错能力。 2工具介绍 为了实现容错处理,就必须能先对异常定位并分析异常,并 给出相应的恢复策略,我们开发了一个工具。这个工具结合抽 象语法树静态分析的信息生成恢复策略,然后自动生成Aspec ̄ 文件,实现异常的修复,达到容错效果。 2.1工具框架介绍 工具的运行过程主要包含两个部分。第一部分,利用抽象 语法树来获取异常所在的方法位置信息、方法参数和方法返回 类型等信息。第二部分,是一个自动生成方面文件的工具。工 具从抽象语法树分析工具分析的结果出发,对异常和异常所在 的方法进行分析,利用string template工具,把抽象语法树中的 分析得到的信息设置到要生成的方面文件中,对每个异常生成 一个默认的方面文件。方面文件动态切入源代码中实现了默认 的异常恢复策略,由于默认异常恢复策略不能保证对所有的异 常处理都有正确的效果,所以工具也允许用户自定制异常恢复 策略,更加灵活和个性化。 2.2抽象语法树分析工具 抽象语法树SAT(Abstract Syntax Tree)是源代码经过词法 分析和语法分析得到的产物,作为程序的一种中间表示形式,能 够包含编译单元的完整表示,可以比较直观地展示整个程序的 语法结构,语法树的建立是在词法分析、语法分析、语义分析的 过程中逐渐产生的。其中词法分析对源程序进行分析,并形成 符号表,作为下一步语法分析做准备,接着语法分析初步形成具 有相应语法结构的中间节点的抽象语法树。最后语义分析,把 名字和操作符进一步处理,产生具有表示类型信息的对象和符 号表的标准的抽象语法树。这时语法树就是完整的抽象语法树 了,它包含了程序结构的基本信息。如图1所示。
图1 int p=0;while(k>0)ll抽象语法树结构 抽象语法树在程序分析和程序开发等诸多领域有广泛的应 用,比如经常用来做代码克隆检测、程序数据流,控制流的分 析等。 为了定位异常产生的位置和异常所在方法和其他方法的调 用关系,这里使用抽象语法树的分析工具来得到程序结构的基 本信息。该工具是一个Eclipse插件,用来做静态代码结构分 析,使用工具可以得到代码中异常的种类,异常所在的类,异常 所在的方法和异常是被catch还是被throw,工具如图2所示。 : …毒 印 _一_ _一…”_ 竺 曼 。 冉 舷 i i 舯酗 r■■_ -__’ 图2抽象语法树代码分析工具 通过该工具可以分析出每个类的方法、参数,抛出的异常以 及每个类之间方法的调用关系,这些信息对于后面生成方面文 件是必不可少的。抽象语法树工具是对源码的静态分析,但是 由于运行时的上下文信息是比较难以获取的,所以我们这里只 对代码做静态分析。根据静态分析得到的信息生成异常处理代 码,正如文献[7]提出的指导原则之一,异常处理必须提供上下 文信息,这里开发者可以利用工具进行进一步的自定制来获取 上下文信息,实现相应的恢复。 2.3设置工具描述 我们开发了一个设置工具,工具中定义了处理异常的面向 方面文件模板,根据模板,利用模板生成工具String Template生 成用于对当前系统做异常处理的方面文件。图3是工具的一个 使用界面。
图3设置工具 首先,选择一个已经用抽象语法树分析过的项目,比如图3 的jforum;然后,由于异常经常是分散在程序中的不同位置,因 此对于抽象语法树分析的结果,我们按照异常的类型来进行分 类,因为同一类型的异常处理方法总是相对于不同类型异常的 处理方法要相似的多;当在ExceptionSetting框中选中特定异常 类型后,抛出这个异常的所有方法,都在第三个框中列出来。包 括类名、方法名、方法参数类型和返回类型。这些信息是生成面 向方面文件的必要信息。 2.4策略的描述 文献[8]提出了一个面向方面的框架来支持Web服务的监 控和恢复,主要是致力于Web服务的运行时监控,以及根据监 控信息来合成Web服务。在恢复的时候,提到三个通用的恢复 策略分别是重试、忽略、可选,但是对于通用策略的代码自动生 成仍然没有做,我们文章试图在通用策略的自动代码生成上做 些尝试。通用恢复策略如图4所示。一般来说,如果重试不成 功,可以忽略(skip)当前异常,或者选用其他可选的方式再重新 尝试,也就是上文所说的可选(alternative)。 对于异常类型和策略的对应关系是一种多对多的关系,同 样是使用的retry策略,但是处理的可能是两种不同的异常。比 如IOException的产生可能是由于远程资源访问不到,而SQLEx. ception可能是数据库的访问出现问题,截然不同的两种异常,
第2期 黄焱艺等:一种面向方面的软件容错能力增强工具
却可以使用同一种retry策略。反过来,当前数据库出现错误, retry通常只能修复那些瞬时性错误,对于非瞬时性的错误更有 效的方法是采取alternative策略自己定制。异常和策略之间的 对应关系是复杂的多对多关系,对这种关系中知识的提取是将 来的一个研究方向。
图4异常和策略映射关系 重试、忽略、可选是通用的异常处理策略,所以我们针对这 三种方法分别设计了一个AspectJ模板,如图5所示。 p曲1ic aftlpe ̄: Retr u 0 m#l 0曲c1£-Tv÷##; #p■m■口lml㈣; 蛐#【cIl。 ‘鼬th f c ¨ 啊-砒咖 #∞tS姗-曲。d酗耻{l¥弛咖址 v ●¥' 强l1l ¥柚t#icM c1e・r霉’K&wi ̄J'tlnl¥c1…“H・-●}【‘-r口-l¥0Bl 瑚I●¥¨ h mer{£Ic雌t她}‘‘t I●lt}‘‘tbi c ‘m眦a f一【 ‘ in^ #P- A●setzct_嘻#; , befof {靶laj H ¥t,Etc ti曲e' { 玎 。#I cb ∞h {#口n1mⅢ{I^ ’c●cch{ ctpti∞el}{ //to∞^眦0—口…●‘td ctt b biae t1.p ^ 3呲 -∞{’; 图5 retry模板 图5中用¥号括起来的是模板生成工具的语法符号,表示 用该模板生成代码的时候这些内容将被具体的内容替代。该模 板是为了生成方面文件的,所以要遵循面向方面编程的语法,下 面我们逐个介绍模板中的元素: Spackage¥:该异常类所在的包名。 SRetryAspectName¥:该方面的方面名。 SdeclearVar¥:用于只带一个参数的方法的参数声明。 SparmDeclearItems¥:用于多个参数的参数声明。 ¥classNameWithoutDot¥¥methodName¥:为了区别每一个 pointcut的名字,用类名和方法名的连接来唯一标识。 SparmsWithVars¥:用来描述带有变量的参数。 ¥metWithDeclear¥:指明调用的方法。 ¥onlyParms¥:指明传递的参数。 ¥ParmsSethems¥:迭代的参数赋值。 该模板包括两个部分,第一部分是获取异常对象当前的方 法,并取得当前的参数,实现方式是通过第一个pointcut,在方法 调用前,将方法参数捕获并将其值传人AspectJ中定义的相应变 量中,这就方便了获取一些运行时的对象信息,开发人员可以在 这里获取自己想要的上下文信息;第二部分,根据当前的对象t 和传递过来的参数列表,对该方法重新执行。如图5所示 t.SmethodName¥(¥onlyParms¥)就是指对当前对象t,执行方法 SmethodName¥,具体方法信息可以从抽象语法树分析出的程 序结构得知当前对象中抛出异常的方法名字。这里retry模板 的advise是重新执行方法。 如图6所示,Skip模板中的advice可以设置为简单抛出一 个运行时异常,相应的,在面向方面中提供了一种弱化异常的方 法,来把方面中抛出的异常继续以运行时异常抛出到原来程序 中,继续运行。Skip可以有三种方式,比如,记录日志并抛出异 常;把返回值设置为默认值;抛出一个运行时异常。由于不同点 在于程序具体的执行和返回状态,文献[7]中指出,开发人员经 常都会倾向于认为,如果当前异常不会影响继续运行,那很多时 候我忽视它是不会产生什么问题的。 0●ah∽l— ■■eI●0t{ ∞^ 呻iⅡt白 h ●,^ 嘲-曲0m“瞳‘‘‘ I—M‘hv- 时’j4-1l e l_tt瓢thDe口王¨ 0 ‘‘姓口nAl#咀聃mI曲 Il‘‘^t I#∞lyh一 ; p。工ntc吐坤 札 ip _#h0 ‘ _#f¥01¨棚-#≈・h锄 枷●,;b●hd #l£ 唧t^驯 ‘‘^ ●‘eJ‘‘tH●c" { be±oH‘lci●_j __eI tt#,0t辨i…,: 抽 St f cry t S ……printI I _ —一-- tip 口I……II 口ⅫEI口”t^*lIj '饥t曲c£^otp≈^∞ti’l tl・pn_t3 c n艚Il } 图6 skip模板 alternative的模板和retry差别在于advice的设置,retry模板的 advice中代码实现方法重新执行,而altemative模板的advice中代 码实现备选方案。实现alternative策略需要用户(即程序的设计人 员)提供备用数据库或者资源文件等的连接信息。当用户选择al— temative的恢复策略时,用户可以手动书写恢复策略代码。
3案例分析
一个开源的论坛系统JForum被选作为实验对象,来验证工 具和方法的可行性。首先,将JForum源代码通过抽象语法树分 析,然后通过工具生成实现了容错策略的方面文件。其次,启动 系统,让系统在正常运行环境中运行。同时一个不带有异常恢 复代码的源程序也在相同环境下运行。在系统抛出异常时,我 们对比两个版本的运行时程序的不同反应,来验证我们方法的 可用性。 在没有做任何恢复处理系统中如果抛出了SQLException和 NuUPointerException,用户会在在浏览器中看到如图7的画面。 用户可能认为该网站出现了严重的错误,已经不可用了。
It ox,qt螂曝饿e ・#_ l确-cot-e.s ・岫蛹 ・pptr・- lo ttt鑫蹲喇 霸岫 矗t oz冒.a M4摊。瑚t- im.o‘’地.孰a ̄Valve.tn1啮糖l|薯皇翻嘲 tt口w.雌t e.毗^重l船-。∞ t.at-| 喇c懈玮尉nV l -轴柙 檀轴誓目‘ ■c o营口-吲 罔妇-口酩^llnt。∞ e・s≮戳硝■ d曩 ●t辅t1 ,l曩 哪l叠i 叫 嘲盘 _t口 卜alpaedte. ̄ ̄alina.,-l珊--霉蚋嘴 删^l t主lI帕t●l葺 嘲羞翻啦钳 图7异常未处理状态 然而,通过工具处理的程序在运行时,如果遇到了相同的问 题,由于加入了retry恢复策略后,如图8所示。 li5:口7;,,.3{7瑚日 ;口 3§ 0 ;m s O,:39.S32 掰1日 S:O :j●。3§4 糟Fb 5: },- 5l 目l曩鼻 ‘---_—’ tHi±l s{07:St.S鞑 1111111 ____-_一ztt£ I} : 5i07:,,.5B2弼嘲 ’—-_---。 j!’1 i5:07:{9。592 W瑚 j‘-____— et玎!}}】 {i5;07Iog.592 l黼 _____—ztt yj}}】 15:∞,:,’.652 F 5:07:j§。,98 瑚Fb 5:口7:,,,0相埘鼬 l砖 e7:40。●‘8 州 lnl帅五“pr l弧t姑i 口E f t ‘0““日r }W.“出i狮# l 1帕岫itor ● chtn E t zd蛳it0r l ^tdn加£ 拍C口nntati∞ l E£ 口r ●-tiag th.d●‘ b-■t c—ec 口艄栩j t#§q ’ 。一 lⅫ 州 ■m口日 l Em %t i埘tht吐.t●bl■e c眦|c H∞0Nl#t靠i锄 }£… g饨e d-t●“…雌f惜c lDBc0咖t0ti口n l z—nr|. i州th●d^tlh,●…c l 鼢∞a● :j镏 l tm 帆-ti加th●d●t■b-●t ca4苴|c lI岫 l I啪ellen,s u-“口 口 lc钾垴口・ }∞ twi_t l I4 ciIl1zing c 0-,.1呻 ●t眦l ‘渤!舢 4e j c1i4 ●t t蚺一《^q t 罅# 图8 retry恢复策略执行后状态 如果retry策略没有效果,系统就会采用ski
p策略,通过把