一种基于执行索引和访问路径的堆区对象比较方法

文档序号:10471052阅读:160来源:国知局
一种基于执行索引和访问路径的堆区对象比较方法
【专利摘要】本发明公开了一种基于执行索引和访问路径的堆区对象比较方法,它包含以下步骤:指定一对匹配的程序执行点,以不同的输入执行同一版本程序(或者以同一输入执行不同版本的程序),在匹配的程序执行点捕获相应的堆区快照;赋予每一个快照中每一个对象一个ID;通过ID将不同快照中的对象进行匹配并递归比较匹配的对象;根据匹配结果,生成差异性度量表。本发明与现有的技术相比,其显著优点是:本发明通过结合两种不同的基本匹配算法,克服了访问路径匹配算法中不能有效匹配数组元素的问题,能够更高效、准确的进行对象比较分析。
【专利说明】
一种基于执行索引和访问路径的堆区对象比较方法
技术领域
[0001]本发明涉及一种基于执行索引和访问路径的堆区对象比较方法,属于程序分析及软件维护等技术领域。
【背景技术】
[0002]现代程序设计语言大多支持面向对象(Object-Oriented)编程范式,例如Ja va、C++、Python。面向对象的程序在执行过程中会创造许多对象。一般来说,对象被随机的动态分配在堆区中,对象之间通过对象的地址,也就是指针,来进行互相访问。面向对象的程序执行实际上是通过对象之间的交互来完成的。因此,对象分析对面向对象程序的分析十分重要。
[0003]对象比较是对象分析的一个重要分支,它主要分为同一次执行不同时间点的对象比较和不同执行间匹配的点之间的比较。一个程序可以接受不同的输入(Input),不同的输入得到不同的执行(Execut1n)。此外,由于软件在不断的更新,一个程序会有多个版本。所以,同一输入在不同版本的程序上也得到不同的执行。一般来说,我们主要关注不同输入的同版本程序的不同执行和相同输入的不同版本程序的不同执行之间的堆区比较。
[0004]本发明主要是解决:相同输入下,不同版本程序的执行过程中创造的对象的比较问题。它可以用来进行调试过程中的缺陷定位以及程序动态更新过程中的对象状态迀移。
[0005]—个面向对象程序有若干类(Class)组成,一个类包含了若干域(Field)和方法(Method),每一个域和方法都有一个唯一的ID。一般来说,对象分为实例(Instance)对象和数组(Array)对象。在程序执行过程中,一个对象占有一定长度的内存空间,该内存空间被分割成槽(Slot)。实例对象由类创造,其包含了该类所包含所有的域,也就是说,每一个域对应一个固定的slot,slot通过对应的域来访问其值(Value)。数组对象由一组数组元素的序列组成,每一个数组元素对应一个slot,slot通过一个数值索引(Index)(即该元素存在于序列中的序号)来访问其值。slot的值分为两种:基本数值(例如整型值)和指针。对于基本数值,比较的时候直接比较其数值,对于指针,比较其是否指向匹配的对象。此外,指针还有一个特殊的值,空指针,表明该指针并没有指向任何对象。
[0006]程序的执行从一个入口方法开始,执行过程中会调用新的方法。方法是用于匹配的最小执行单元,每一个方法有一个固定的标识符(ID)。不同版本之间的方法可以有相同的ID,但是有不同的代码实现。在一个程序的执行点,我们可以得到一个活动方法的调用序列,从入口方法开始到当前方法。通过这个调用序列,我们可以生成一个Call String。一个Call String是一个由方法ID、该方法当前的指令以及通过该指令调用该方法的次数组成的三元组的序列。除了序列中的最后一个三元组,其余三元组的当前指令必然是一条调用指令。这里,我们用Call String来刻画和匹配程序执行点。在匹配同一版本的不同执行的Call String时,我们只匹配方法ID。在匹配不同版本的不同执行时,除了方法ID,其方法代码也要一致才能匹配。
[0007]对象比较一般需要先匹配对象,然后比较匹配对象各个slot值的差异。匹配对象需要首先为每一个对象指派一个标识符(ID),然后将相同ID的对象匹配。最简单的对象ID是对象的地址,但是由于地址分配的随机性,因此该ID不适合不同执行之间的对象比较。另外一种ID是关键域(Key Fields),这种ID能够区分同一个类的不同对象,又能匹配两个集合中的同一个类的对象,但是为了找到能够满足条件的域,对于集合中的每一个对象,算法都需要在另一个集合中遍历,复杂度为0(n2),而且该类中域的语义也不一定满足这种严格的要求,所以这种算法使用范围小,复杂度比较高。还有一种简单的ID是采用计数器,每一个对象按照创建的顺序分配ID。这种ID在局部范围(例如一段顺序执行的代码)有不错的效果,但是在分支较多的程序中,由于不同执行选择的分支执行顺序不同(例如插入执行一段分支),会导致ID差异很大。一种弥补这种程序结构带来的影响办法是通过结构化的执行索引来。
[0008]执行索引反映了程序执行的时间点,它将程序执行过程遇到的每条指令的执行给予一个在本次执行中唯一编号,例如上述的计数器就可以实现这样的编号。但是这种索引没有考虑到程序的结构信息和上下文信息,例如Call String。一些已有的高级执行索引考虑到了这些信息,可以提供很好的执行匹配。但是问题是由于不同执行会执行不同的代码,调用不同的方法,因此并不是所有的Call String可以匹配。这个时候,要考虑堆区的拓扑结构来弥补。
[0009]堆区中对象可以组织成一个有向图(R,V,E),其中R为一个根指针集合,包含全局变量和当前的局部变量;V为点(对象)的集合,包含堆区中的对象集合;E是边(指针)的集合,包含根指针和对象slot内的指针。每条边都有一个标签,对于根指针则为相应的变量的名称,对于实例对象里的域,则为该域的ID,对于数组元素,则为该元素的索引。在任意的执行时刻点,根指针集合可以唯一确定。对象的访问都是通过指针来进行。从根指针开始,我们可以通过一系列指针,访问到任意的可访问的堆区对象。这个指针序列就是访问路径(Access Path)。获得访问路径的方式有很多种,一种常见的是就是从根指针开始,生成有向图的深度优先搜索树,那么树中的一条路径(这里边是指针)就是一条访问路径。
[0010]访问路径作为对象的ID可以有效匹配对象,但是若路径中存在一个数组元素,则该匹配效果会很差。这是由于不同执行元素插入数组的顺序不同从而导致索引不同,此外,一些元素的索引是不确定的哈希值计算得到。为了弥补这个问题,一个自然而然的解决方式就是结合多种匹配方法,互取长短。因此,本发明提出了一种结合访问路径和执行索引的堆区对象比较方法。

【发明内容】

[0011 ]由于对象是存在于程序执行过程的内存中的,当我们需要分析对象的时候,需要在一些程序执行点,通过一些工具捕获内存中的对象,存入一个快照当中以便分析。本发明所要解决的技术问题是比较不同堆区快照中的对象,度量不同快照的差异性大小。
[0012]本发明的技术方案为:一种基于执行索引和访问路径的堆区对象比较方法,它包含以下步骤:
[0013]I)指定一对匹配的程序执行点,以不同的输入执行同一版本程序(或者以同一输入执行不同版本的程序),在匹配的程序执行点捕获相应的堆区快照;
[0014]2)赋予每一个快照中每一个对象一个ID;
[0015]3)通过ID将不同快照中的对象进行匹配并递归比较匹配的对象;
[0016]4)根据匹配结果,生成差异性度量表。
[0017]步骤I)的具体步骤包括:
[0018]1.1)读取配置文件,指定匹配点的CalI String;
[0019]1.2)通过代码插粧框架在方法的入口插入构建并检测Call String的代码,同时记录每个对象创建时的Call String;
[0020]1.3)执行插粧后的程序;
[0021]1.4)若检测到匹配的Call String,则生成堆区快照。
[0022]步骤1.2)中构建和检测Call String,记录对象创建的代码执行过程如下:
[0023 ] 1.2.1)初始化调用树,从程序的主线程入口开始记录;
[0024]1.2.2)在每一个函数的入口,我们都记录下当前方法的ID、调用该方法的指令,以及它的执行次数;
[0025]1.2.3)当拦截到新的对象创建时,生成该对象对应执行点的Call String,并记录到该对象中,同时保存到一个全局的哈希表中;
[0026]1.2.4)当检测到执行点的Call String与匹配点的Call String相同时,我们就生成当前堆区的快照。
[0027]步骤2)中赋予每一个对象一个ID的具体步骤如下:
[0028]2.1)初始访问路径为空,根据变量名匹配根指针;
[0029]2.2)从匹配的根指针开始,同时深度遍历两个堆区快照,并将访问的指针追加于访问路径之上;
[0030]2.3)若通过匹配的指针访问的一对对象类型相同,则匹配该对象,否则不匹配;[0031 ] 2.4)对于匹配的对象,若该对象是实例对象,则直接匹配相同ID域指针;
[0032]2.5)若该对象是数组对象,则结合Call String匹配数组元素的指针。
[0033]步骤2.5)中匹配数组元素指针的具体步骤如下:
[0034]2.5.1)从第一个堆区快照中取出一个不为空的数组元素指针(即该指针指向一个对象);
[0035]2.5.2)若第二个堆区快照中存在一个同样不为空的数组元素指针,且这两个指针指向的对象有匹配的Call String,则匹配这两个数组元素指针;
[0036]2.5.3)依次执行前两步,不断从第一个堆区快照中取出不为空的数组元素指针,直到该数组对象没有不为空的数组元素指针为止。
[0037]步骤3)中比较匹配的对象的具体步骤如下:
[0038]3.1)若匹配的对象是实例对象,则比较匹配的域的值,若存在不同值的域,则标记该对象不同;
[0039]3.2)若匹配的对象是数组对象,则首先比较其数组元素个数。若数组元素个数不同,则标记该对象不同;
[0040]3.3)若数组元素相同,且该数组元素的类型为基本数值,则按照匹配的索引比较对应数组元素的数值;若存在任意不同数值的数组元素,则标记该对象不同;
[0041]3.4)若数组元素相同,但该数组元素的类型为指针,若存在任意不匹配的指针,则标记该对象不同。
[0042]步骤4)中统计度量信息,生成度量表的步骤包括:
[0043]4.1)把匹配的Call String作为时序标志,对齐快照,作为横轴;
[0044]4.2)对于每对快照,度量值=相同对象的个数/总的对象个数,作为纵轴;
[0045]4.3)生成图表信息。
[0046]本发明与现有的技术相比,其显著优点是:
[0047]I)高性能:使用CalI String记录对象创建时的上下文信息,并借助于哈希表保存了Call String和对象的对应关系,能够快速获得匹配的对象,因此相对于Key Fields算法的复杂度,由原来的0(n2)降为现在的0(n);
[0048]2)准确性:扩展了访问路径匹配算法,利用Call String保留的对象创建时的上下文信息,匹配了更多的对象。
【附图说明】
[0049]图1为本发明进行堆区对象比较时的关键步骤示意图。
[0050]图2为本发明实施的主要流程图。
【具体实施方式】
[0051]以下结合附图和具体实施例对本发明作进一步详细说明。
[0052]本发明通过结合两种不同的基本匹配算法,克服了访问路径匹配算法中不能有效匹配数组元素的问题,能够更高效、准确的进行对象比较分析。
[0053]为了实验验证我们的方法,图2给出了具体的实施过程。首先获取两个版本的Java程序代码,进行静态代码插粧,然后运行插粧后的代码并记录快照。这其中使用了两个工具:一个是Java虚拟机工具接口( JVMTI),一个是字节码增强工具(java_crw_demo)。
[0054]JVMTI是虚拟机提供的用于监听方法执行、对象生成、线程执行等活动的工具接口,我们开发了一个使用该接口获取方法执行和对象创建信息的Agent,并使用字节码增强工具修改了对象的构造函数。修改后的构造函数能够自动将对象创建时生成的C a 11String保存到该对象中。为了指定匹配点的Call String,我们首先使用一个jar包比较工具(UPT)来获取类更新信息,并保存到指定的规约文件中。在执行插粧后的程序时,读取该规约文件,把文本中记录的类修改信息记录到运行时用于判别Call String的对象中,当检测到匹配的Ca 11 Str ing时,则生成堆区快照。
[0055]获得快照以后,我们使用比较工具分别读取每对快照。首先解析该快照,获得对象图,然后匹配对象图的Root集合,并同时遍历两个堆区快照,将访问的指针追加于访问路径之上。根据指针指向的对象类型,我们进行分别处理,获得匹配信息(具体情况,请看
【发明内容】
的步骤2)。这里我们使用了Open JDK开发包中提供的hat接口,用于初步解析获得的快照文件。图1为本发明进行堆区对象比较时的关键步骤示意图。
[0056]以上结合附图和具体实施例对本发明的实施方法作了详细的说明,但是本发明不限于上述实施方式,在所属技术领域普通技术人员所具备的知识范围内,还可以在不脱离本发明宗旨的前提下做出各种常规变化,但均在本发明权利要求书的保护范围之内。
【主权项】
1.一种基于执行索引和访问路径的堆区对象比较方法,其特征在于,它包含以下步骤: 步骤一、指定一对匹配的程序执行点,以同一输入执行不同版本的程序,或者以不同的输入执行同一版本的程序,在匹配的程序执行点捕获相应的堆区快照; 步骤二、赋予每一个快照中每一个对象一个ID; 步骤三、通过ID将不同快照中的对象进行匹配,比较匹配的对象,从而获得每对快照的差异性度量值。2.根据权利要求1所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于,步骤一中获取堆区快照的步骤包括: 步骤I.I指定匹配点的Call String; 步骤1.2通过代码插粧框架在方法的入口插入构建并检测Call String的代码,同时记录每个对象创建时的Call String; 步骤1.3执行插粧后的程序,若检测到匹配的Call String,则生成堆区快照。3.根据权利要求2所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于,步骤1.2中构建和检测Call String,记录对象创建的代码执行过程如下: 步骤1.2.1初始化调用树,从程序的主线程入口开始记录; 步骤1.2.2在每一个函数的入口,都记录下当前方法的ID、调用该方法的指令,以及它的执行次数; 步骤1.2.3当拦截到新的对象创建时,生成该对象对应执行点的C a 11 S t r i n g,并记录到该对象中,同时保存到一个全局的哈希表中; 步骤1.2.4当检测到执行点的Call String与匹配点的Call String相同时,就生成当前堆区的快照。4.根据权利要求1所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于,步骤二中赋予每一个对象一个ID的具体步骤包括: 步骤2.1初始访问路径为空,根据变量名匹配根指针; 步骤2.2从匹配的根指针开始,同时深度遍历两个堆区快照,并将访问的指针追加于访问路径之上; 步骤2.3若通过匹配的指针访问的一对对象类型相同,则匹配该对象,否则不匹配; 步骤2.4对于匹配的对象,若该对象是数组对象,则结合CalI String匹配数组元素的指针。5.根据权利要求4所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于:步骤2.4中对于匹配的对象,若该对象是实例对象,则直接匹配相同ID域指针。6.根据权利要求5所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于:步骤2.4中对于匹配的数组对象,从一个堆区快照中依次获取该对象不为空的元素指针,与另一个堆区快照中的数组对象的元素指针进行匹配,若这个两个指针指向的对象有相同的Call String,则匹配这两个数组元素指针。7.根据权利要求5所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于,步骤2.4中匹配数组元素指针的具体步骤如下: 步骤2.4.1从第一个堆区快照中取出一个不为空的数组元素指针,即该指针指向一个对象; 步骤2.4.2若第二个堆区快照中存在一个同样不为空的数组元素指针,且这两个指针指向的对象有匹配的Call String,则匹配这两个数组元素指针; 步骤2.4.3依次执行前两步,不断从第一个堆区快照中取出不为空的数组元素指针,直到该数组对象没有不为空的数组元素指针为止。8.根据权利要求5所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于,步骤三中比较匹配的对象的具体步骤如下: 步骤3.1若匹配的对象是实例对象,则比较匹配的域的值,若存在不同值的域,则标记该对象不同; 步骤3.2若匹配的对象是数组对象,则首先比较其数组元素个数;若数组元素个数不同,则标记该对象不同; 步骤3.3若数组元素相同,且该数组元素的类型为基本数值,则按照匹配的索引比较对应数组元素的数值;若存在任意不同数值的数组元素,则标记该对象不同; 步骤3.4若数组元素相同,但该数组元素的类型为指针,若存在任意不匹配的指针,则标记该对象不同。9.根据权利要求8所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于,步骤三中统计度量信息,生成度量表的步骤包括: 步骤3.5把匹配的CalI String作为时序标志,对齐快照,作为横轴; 步骤3.6对于每对快照,度量值=相同对象的个数/总的对象个数,作为纵轴; 步骤3.7生成图表信息。
【文档编号】G06F11/36GK105824758SQ201610158676
【公开日】2016年8月3日
【申请日】2016年3月21日
【发明人】刘锐奇, 顾天晓, 马晓星, 曹春
【申请人】南京大学
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1