面向客户端应用程序的获取运行时软件体系结构的方法与流程

文档序号:16692521发布日期:2019-01-22 19:02阅读:278来源:国知局
面向客户端应用程序的获取运行时软件体系结构的方法与流程

本发明属于软件技术领域,尤其涉及一种面向客户端应用程序的获取运行时软件体系结构的方法。



背景技术:

运行时软件体系结构是系统运行时刻的一个动态、结构化的抽象,描述系统当前的组成成分、各成分的状态和配置以及不同成分之间的关系。运行时体系结构与目标系统间具有动态的因果关联,即系统的变化及时体现在体系结构上,而对体系结构的修改及时影响当前系统。运行时体系结构允许开发者以读写体系结构的方式实现系统的监测和调整,是体系结构层次系统动态适应与在线演化的基础。

现如今,随着互联网的发展,出现了大量的客户端应用程序,并且数量仍然在快速增长,这些应用程序更新换代的速度也越来越快,然而它们的更新速度仍然远远不及硬件的发展速度,为了能加快应用软件的更新和演化,产生了能在客户端程序运行时,实时看到系统运行时的软件体系结构的迫切需求,目前,在现有技术当中,尚无较为可靠和成体系的具备普适性的获取运行时软件体系结构的方法。



技术实现要素:

本发明目的在于提出一种面向客户端应用程序的获取运行时软件体系结构的方法,有利于研究人员熟悉系统,同时也能大大促进系统的升级和演化的速度。本发明采用的基本设计思路在于:对于一个给定的客户端应用程序,首先对它的源程序代码中的所有类进行预处理,即当发现有对象被创建时,就记录当前创建的对象与创建对象的位置。预处理完后进行对象的转换,这步需要用到代理模式,同步构造一个与其等价的代理对象,可为目标对象提供另外的访问方式,即通过代理对象访问目标对象。最后,获取运行时的信息。通过代理模式,为所有运行时对象创建代理类。拦截器会拦截所有运行时使用的类,然后通过一些记录调用路径的函数及数据结构来确定对象间的关系,并记录下相关信息,例如调用方法,输入参数,输出结果等等。通过上述步骤就可以在不改变软件功能和外部可见性的情况下得到系统运行时的软件体系结构。

本发明具体采用以下技术方案:

一种面向客户端应用程序的获取运行时软件体系结构的方法,其特征在于,包括以下步骤:

步骤s1:对客户端应用程序的源程序代码中的所有类进行预处理:当发现有源对象被创建时,记录当前创建的对象与创建对象的位置;

步骤s2:进行对象的转换:采用代理模式,同步构造一个与源对象等价的代理对象,通过代理对象访问目标对象;

步骤s3:获取运行时的信息:通过代理模式,为所有运行时的对象创建代理类;通过拦截器拦截所有运行时使用的类,然后通过记录调用路径的函数及数据结构来确定对象间的关系,并记录下运行时的信息。

进一步地,所述源程序代码采用java编程;

所述源对象和代理对象的关系定义为:

p=<object,proxy>(1)

其中,proxy为代理对象,object为源对象;

创建对象的位置和被创建的对象的关系定义为:

objectid=<pos,object>(2)

其中,pos为创建对象的位置,object为被创建的源对象;

对象声明路径定义为:

p=<method1,method2,…,methodn>(3)

methodi为函数;

对象调用关系定义为:

g=<object,invoke>(4)

invoke为对象所调用的函数;

函数的参数列表定义为:

para=<parameter1,parameter2,…,parametern>(5)

其中,parameteri=<value,type>为第i个参数,参数值为value,参数类型为type;

某个功能的输入、输出、调用函数序列定义为:

func=<input,output,queries>(6)

因为运行时软件体系结构是根据各个功能而相互独立的,所以对各个功能单独定义,其中,input是用户想要执行某个功能所需填入的参数,output是操作完成后获得的数据,queries是调用该功能所需要执行的一系列操作,从input获取数据,执行数据处理,将数据填充到output中;

输入定义为:

input={<i1,vi1>,<i2,vi2>…<in,vin>}(7)

<ii,vii>表示第i个参数,ii表示参数类型,vii表示参数值;

输出定义为:

output={<o1,vo1>,<o2,vo2>…<on,von>}(8)

<oi,voi>表示第i个返回的数据,oi表示返回类型,voi表示返回值;

执行某个功能所调用的函数序列定义为:

queries={t1,t2,…,tn}(9)

queries表示执行某个功能的请求序列,ti表示第i个请求;

步骤s1具体包括以下步骤:

步骤s11:扫描客户端应用程序的源程序代码,在每个主函数的开头加入以下代码:

stringcurrentname=thread.currentthread().getstacktrace()[1].getclassname()+'.'+thread.currentthread().getstacktrace()[1].getmethodname();/获取当前包名及方法名

currentobject.push(currentname);//将方法名压入栈

步骤s12:在源程序代码的每个函数开头加入以下代码:

stringcurrentname=thread.currentthread().getstacktrace()[1].getclassname()+'.'+thread.currentthread().getstacktrace()[1].getmethodname();//获取当前包名及方法名

步骤s13:在每个对象创建后加入一行函数调用,如对于对象a有:

objecta=newobject();

a=(object)cglibfactory.getproxyinstance(a,currentname);。

进一步地,在步骤s2中,当有对象被创建时,调用代理函数为源对象创建代理对象:

根据objectid=<pos,object>赋值objectid为“创建对象的方法名@对象名”

enhancerenhancer=newenhancer();

enhancer.setsuperclass(object.getclass());

enhancer.setcallback(newmycglibproxy(object,objectid));

//设置回调函数存储源对象声明路径p=<method1,method2,…,methodn>

objectproxy=enhancer.create();。

进一步地,在步骤s2中,将代理对象和源对象以指定格式存储在各个表中:

将源对象和代理对象的一一对应关系p=<object,proxy>存储在名为objectpp的map<object,object>中;

将objectid和代理对象一一对应存储在名为objectfactory的map<string,object>中;

将源对象和objectid一一对应存储在名为object_id_map的哈希表中。

进一步地,步骤s3具体包括以下步骤:

步骤s31:当前源对象有方法调用时,自动调用方法拦截器:

将调用方法的对象和调用的方法名存储成指定格式:

stringdproxied=domain.object_id_map.get(proxied);//获取源对象名

stringdmethod=dproxied+':'+method.getname()+"(";

class[]paramtypes=method.getparametertypes();

for(classclass1:paramtypes){//存储参数列表para=<parameter1,parameter2,…,parametern>

dmethod=dmethod+class1.getname();

}

dmethod=dmethod+")";

步骤s32:将获得的信息以指定格式存储在各个数组和表中:

arraylist<string>tmp=newarraylist<string>();

tmp.add(dmethod);

主函数所在类名.relation.put(invoker,tmp);

主函数所在类名.evaluate.add(invoker+"--->"+dmethod);

主函数所在类名.currentobject.push(dmethod);。

进一步地,为了实现可见性,在步骤s3之后,还包括步骤s4:输出形式化后的运行时软件体系结构。

本发明及其优选方案通过可靠的手段获取运行时软件体系结构,提供了以读写体系结构的方式实现系统的监测和调整的途径,为系统的在线升级和演化提供了基础,本发明通过代理模式实现了运行时对象的代理,获取了系统运行时的信息,实现了在不改变软件功能和外部可见性的情况下得到系统运行时的软件体系结构,降低了系统开发和升级的难度,提高了系统演化的效率。

附图说明

下面结合附图和具体实施方式对本发明进一步详细的说明:

图1是本发明实施例源结构示意图;

图2是本发明实施例目标结构示意图;

图3是本发明实施例获取和重建软件体系结构步骤示意图;

图4是本发明实施例代理对象格式示意图;

图5是本发明实施例采用的实验系统部分原代码示意图;

图6是本发明实施例采用的实验系统经过预处理后的代码示意图;

图7是本发明实施例采用的实验系统的界面示意图1;

图8是本发明实施例采用的实验系统的界面示意图2;

图9是本发明实施例采用的实验系统的界面示意图3;

图10是本发明实施例采用的实验系统经过本实施例方法处理后获得的软件体系结构图。

具体实施方式

为让本专利的特征和优点能更明显易懂,下文特举实施例,作详细说明如下:

本发明实施例旨在通过本发明提供的方法获取运行时软件体系结构并完成软件体系结构的重建,软件体系结构重建的原则是重建给定的代码而不改变其外部功能。一般来说,重建具有三个方面的特征:(1)原始代码的结构,即源结构;(2)目标代码的结构,即目标结构;(3)一系列代码重建步骤,将原始代码转换为功能等效的目标代码,以便目标代码最终能够呈现所需的程序结构。

其中,源结构,即原始代码的结构。如图1所示,独立客户端系统中给定代码的源结构采用了本地调用方式。类x首先获取类n的内存引用,然后调用n的方法。显然,这种简单的结构并不支持对运行时类n进行随时管理。倘若想要获取运行时类n中的某个参数或者对其进行修改,原始结构并不可行。

如图2所示,展示了本实施例提出的重建运行时软件体系的目标结构。能够随时获取运行时类的构成元素,并进行修改。结构的核心由两个元素组成:proxy和pathservice。

图2中的代理nproxy,与类n的作用相同,只是它本身不做任何计算,而是将方法调用转发给后者。拦截器会负责确定n的当前对象和方法,并将方法调用转发给代理nproxy。如果运行时对类n的某个参数进行更改,只需要对nproxy的信息进行改变,而不用操作源代码。这样,此次变化只会对当前状态发生作用,而不会影响到整个程序。

pathservice主要负责确定对象间的调用关系。当类x调用类n的某个方法时,会确定x和n的一个关系,通过栈的方式分别记录下来。记录下完成系统功能的过程,后用反射的方式完成功能的重现。

如图3所示,在给定的独立客户端系统的java字节码上执行一系列重建步骤,这样图1中所示的源代码结构就可以转换为图3所示的目标结构。以此重建运行时软件体系结构,为系统的升级演化提供相应的信息。

在代码重建的过程当中,最关键的过程即为运行时软件体系结构的获取,其包括以下具体步骤:

(1)获取运行时对象。对于一个给定的java应用,所有的类都需要进行预处理。当发现有对象被创建时,例如,aa=newa(),记录当前创建对象与创建位置。

(2)对象转换。为获取运行时对象,需要对上一步记录的对象位置进行转换。使用代理模式,同步构造一个与其等价的代理对象,可为目标对象提供另外的访问方式,即通过代理对象访问目标对象。这样可以在目标对象实现的基础上,扩展目标对象的功能,为后续重建运行时软件体系结构提供方便。格式如图4所示;

(3)获取运行时信息。通过代理模式,为所有运行时对象创建代理类。拦截器会拦截所有运行时使用的类,通过上述pathservice来确定对象间的关系,并记录下相关信息,例如调用方法,输入参数,输出结果等等。

以上过程的形式化表述如下:

step1:对客户端应用进行预处理

(1)扫描客户端源代码,在每个主函数的开头加入以下代码:

stringcurrentname=thread.currentthread().getstacktrace()[1].getclassname()+'.'+thread.currentthread().getstacktrace()[1].getmethodname();//获取当前包名及方法名

currentobject.push(currentname);//将方法名压入栈

(2)在每个函数开头加入以下代码:

stringcurrentname=thread.currentthread().getstacktrace()[1].getclassname()+'.'+thread.currentthread().getstacktrace()[1].getmethodname();//获取当前包名及方法名

(3)在每个对象创建后加入一行函数调用,如:

objecta=newobject();

a=(object)cglibfactory.getproxyinstance(a,currentname);

step2:当有对象被创建时,调用代理函数为源对象创建代理对象:

根据objectid=<pos,object>赋值objectid为“创建对象的方法名@对象名”

enhancerenhancer=newenhancer();

enhancer.setsuperclass(object.getclass());

enhancer.setcallback(newmycglibproxy(object,objectid));

//设置回调函数存储源对象声明路径p=<method1,method2,…,methodn>

objectproxy=enhancer.create();

step3:将代理对象和源对象以指定格式存储在各个表中:

将源对象和代理对象的一一对应关系p=<object,proxy>存储在名为objectpp的map<object,object>中。

将objectid和代理对象一一对应存储在名为objectfactory的map<string,object>中。

将源对象和objectid一一对应存储在名为object_id_map的哈希表中。

step4:当前源对象有方法调用时,自动调用方法拦截器:

将调用方法的对象和调用的方法名存储成指定格式:

stringdproxied=domain.object_id_map.get(proxied);//获取源对象名

stringdmethod=dproxied+':'+method.getname()+"(";

获取所调用方法的参数,处理成指定格式:

class[]paramtypes=method.getparametertypes();

for(classclass1:paramtypes){//存储参数列表para=<parameter1,parameter2,…,parametern>

dmethod=dmethod+class1.getname();

}

dmethod=dmethod+")";

step4:将上述获得的信息以指定格式存储在各个数组和表中:

arraylist<string>tmp=newarraylist<string>();

tmp.add(dmethod);

主函数所在类名.relation.put(invoker,tmp);

主函数所在类名.evaluate.add(invoker+"--->"+dmethod);

主函数所在类名.currentobject.push(dmethod);

step5:为了可见性,输出形式化后系统运行时软件体系结构。

总结而言,获取运行时信息的算法具体包括:

输入:给定的客户端应用程序;

输出:运行时软件体系结构;

步骤1:将该客户端应用程序进行预处理;

步骤2:当前有对象被创建,调用代理函数;

步骤3:赋值objectid为“创建对象的方法名@对象名”;

步骤4:为源对象创建相同类型的代理对象;

步骤5:回调函数存储源对象声明路径;

步骤6:将源对象和代理对象一一对应地存储在名为objectpp的map<object,object>中;

步骤7:将objectid和代理对象一一对应存储在名为objectfactory的map<string,object>中;

步骤8:将源对象和objectid一一对应存储在名为object_id_map的哈希表中;

步骤9:当前源对象有方法调用时,自动调用方法拦截器;

步骤10:将调用方法的对象和调用的方法名存储成指定格式;

步骤11:获取所调用方法的参数,处理成指定格式;

步骤12:将上述获得的信息以给定格式存储在数组中;

步骤13:按给定格式输出系统运行时软件体系结构。

在本实施例中,采用上述方案对实验系统——超市管理系统进行验证,对于其中仓库管理员登录并查询商品的功能,系统原来的部分代码如图5所示,预处理后的代码如图6所示。

仓库管理员登录并查询商品的系统界面如图7-图9所示。

获得的运行时软件体系结构打印出来如下(删去一些界面控件生成的部分,使其格式较为简洁):

com.jie.view.domain.main(string[])--->

com.jie.view.domain.main(string[])@com.jie.view.loginview[]:actionperformed(java.awt.event.actionevent)--->

com.jie.view.loginview.actionperformed()@com.jie.model.model@6b4dd06e:dologin(java.lang.stringjava.lang.string)

com.jie.view.domain.main(string[])--->

com.jie.view.loginview.actionperformed()@com.jie.view.warehouseview[]:actionperformed(java.awt.event.actionevent)--->

com.jie.view.warehouseview.actionperformed()@com.jie.entity.entity@7ac7d102:setgoodsid(java.lang.string)

com.jie.view.loginview.actionperformed()@com.jie.view.warehouseview[]:actionperformed(java.awt.event.actionevent)--->

com.jie.view.warehouseview.actionperformed()@com.jie.model.model@18feeea2:goodsfindbyid(java.lang.string)

由此可以分析生成仓库管理员登录并查询商品功能的软件体系结构图,如图10所示。

本专利不局限于上述最佳实施方式,任何人在本专利的启示下都可以得出其它各种形式的面向客户端应用程序的获取运行时软件体系结构的方法,凡依本发明申请专利范围所做的均等变化与修饰,皆应属本专利的涵盖范围。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1