基于反射的安卓应用微服务化方法及系统转让专利

申请号 : CN201811012655.5

文献号 : CN109189469B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 黄罡蔡华谦骆宇冲张颖刘譞哲

申请人 : 北京大学

摘要 :

本发明公开了一种基于反射的安卓应用微服务化方法及系统,通过对安卓应用运行进行监控,得到应用的行为反射运行时模型,并在其中的运行时栈模型中标注包含目标数据的目标对象,生成目标对象的所有函数调用集,再根据使用函数调用集生成函数调用代码的难度为每一函数调用集进行评分,并根据评分推荐函数调用集以生成可执行的函数调用代码。对不能在运行时栈模型中生成的目标对象,在运行时堆模型中生成目标对象的所有引用链,并构造类加载器,再根据被选择的目标对象引用链生成目标对象构造代码,最后再将生成的函数调用代码和目标对象构造代码结合起来包装成微服务接口。本发明能大大减少开发安卓应用微服务的时间,有效解决安卓应用微服务开发中执行序列复杂与数据依赖复杂两大难题。

权利要求 :

1.一种基于反射的安卓应用微服务化方法,其特征在于,包括如下步骤:步骤S1:在安卓应用运行时,对所述安卓应用的运行进行监控,得到所述安卓应用的行为反射运行时模型,然后跳转至步骤S2;所述行为反射运行时模型包括运行时栈模型和运行时堆模型;

步骤S2:标注所述运行时栈模型中包含目标数据的目标对象,然后跳转至步骤S3;

步骤S3:生成所述目标对象的所有函数调用集,然后跳转至步骤S4;

步骤S4:分析使用每一函数调用集生成函数调用代码的难度,并据此为每一函数调用集进行评分,然后跳转到步骤S5;

步骤S5:判断被选择的函数调用集是否依赖新对象,当所述被选择的函数调用集依赖新对象时,跳转至步骤S2,并将依赖的新对象作为所述目标对象,否则跳转至步骤S6,所述被选择的函数调用集为根据各函数调用集的评分从所述所有函数调用集中选择的;

步骤S6:将各次选择的函数调用集按序组成函数调用序列,并使用所述函数调用序列生成可执行的函数调用代码;

步骤S7:对于无法在所述运行时栈模型中生成的目标对象,在所述运行时堆模型中,根据目标对象间的引用信息生成所述目标对象的所有引用链;

其中所述步骤S7包括:

步骤S7A:从目标对象开始,遍历引用了该目标对象的对象,并判断引用了该目标对象的对象的类型,所述类型包括基础数据类型对象、普通堆对象、类对象、数组对象和引用对象;

步骤S7B:如果当前遍历到的对象不是一个类对象,则继续以此对象为新的目标对象进行下一轮遍历,如果当前遍历到的对象是一个类对象,查找该对象的一个静态成员变量,并根据所述静态成员变量与目标对象间的引用关系,得到目标对象的一条引用链;

步骤S7C:重复步骤S7A和步骤S7B,直到得到所有以目标对象结尾,以所述静态成员变量开头的引用链;

步骤S8:判断被选择的目标对象引用链开头的静态对象的类加载器是否与应用类加载器一致,如果不一致,则将所述类加载器作为新的目标对象返回执行步骤S7,如果一致则执行步骤S9;

步骤S9:根据被选择的目标对象引用链生成目标对象构造代码;

步骤S10:将所述函数调用代码和目标对象构造代码包装成微服务接口。

2.如权利要求1所述的基于反射的安卓应用微服务化方法,其特征在于,所述步骤S4中,分析使用函数调用集生成函数调用代码的难度,并据此为该函数调用集进行评分的步骤包括:统计该函数调用集中函数调用的数目A;

统计该函数调用集所依赖的新对象的数目B;

统计该函数调用集所依赖的所有新对象的总相关函数调用的数目C;

统计该函数调用集中无法在运行时栈模型中构造的新对象数目D;

根据数目A、数目B、数目C及数目D各自的预设权重,将数目A、数目B、数目C及数目D进行加权求和,得到该函数调用集的评分。

3.如权利要求1所述的基于反射的安卓应用微服务化方法,其特征在于,所述步骤S3中,生成所述目标对象的所有函数调用集包括如下步骤:查找所述目标对象从第一次出现到包含所述目标数据的过程中所有调用的函数以及所有以所述目标对象为参数的函数;

依据运行时栈模型提供的函数调用栈信息,将查找到的函数划分成调用栈层次不完全相同但最后执行逻辑相同的多个函数调用集。

4.如权利要求1所述的基于反射的安卓应用微服务化方法,其特征在于,执行所述步骤S7B时,实时记录当前引用链中已经使用的对象,如果遍历过程中遇到了已经使用过的对象,则跳过该对象。

5.一种基于反射的安卓应用微服务化系统,其特征在于,包括:网构软件行为反射技术框架、目标对象标注模块、函数调用集生成模块、函数调用集评分模块、判断模块、函数调用代码生成模块、目标对象引用链生成模块、类加载器构造模块、目标对象构造代码生成模块和微服务化接口包装模块;

所述网构软件行为反射技术框架,用于在安卓应用运行时,对所述安卓应用的运行进行监控,得到所述安卓应用的行为反射运行时模型,所述行为反射运行时模型包括运行时栈模型和运行时堆模型;

所述目标对象标注模块,用于标注所述运行时栈模型中包含目标数据的目标对象;

所述函数调用集生成模块,用于生成所述目标对象的所有函数调用集;

所述函数调用集评分模块,用于分析使用每一函数调用集生成函数调用代码的难度,并据此为每一函数调用集进行评分;

所述判断模块,用于判断被选择的函数调用集是否依赖新对象,当所述被选择的函数调用集依赖新对象时,返回运行所述目标对象标注模块,并将依赖的新对象作为所述目标对象,否则运行所述函数调用代码生成模块,所述被选择的函数调用集为根据各函数调用集的评分从所述所有函数调用集中选择的;

所述函数调用代码生成模块,用于将各次选择的函数调用集按序组成函数调用序列,并使用所述函数调用序列生成可执行的函数调用代码;

所述目标对象引用链生成模块,用于根据目标对象间的引用信息生成所述目标对象的所有引用链;其中目标对象引用链生成模块包括遍历模块、引用链生成子模块;

遍历模块用于从目标对象开始,遍历引用了该目标对象的对象,并判断引用了该目标对象的对象的类型,所述类型包括基础数据类型对象、普通堆对象、类对象、数组对象和引用对象,并在当前遍历到的对象不是一个类对象,则继续以此对象为新的目标对象进行下一轮遍历;

引用链生成子模块用于在遍历模块当前遍历到的对象是一个类对象时,查找该对象的一个静态成员变量,并根据所述静态成员变量与目标对象间的引用关系,得到目标对象的一条引用链,并返回运行所述遍历模块,直到得到所有以目标对象结尾,以所述静态成员变量开头的引用链;

所述类加载器构造模块,用于判断被选择的目标对象引用链开头的静态对象的类加载器是否与应用类加载器一致,如果不一致,则将所述类加载器作为新的目标对象返回运行所述目标对象引用链生成模块;

所述目标对象构造代码生成模块,用于根据被选择的目标对象引用链生成目标对象构造代码;

所述微服务化接口包装模块,用于将所述函数调用代码和目标对象构造代码包装成微服务接口。

6.如权利要求5所述的基于反射的安卓应用微服务化系统,其特征在于,所述函数调用集评分模块包括:统计模块,用于统计函数调用集中函数调用的数目A、该函数调用集所依赖的新对象的数目B、该函数调用集所依赖的所有新对象的总相关函数调用的数目C,以及该函数调用集中无法在运行时栈模型中构造的新对象数目D;

加权求和模块,用于根据数目A、数目B、数目C及数目D各自的预设权重,将数目A、数目B、数目C及数目D进行加权求和,得到该函数调用集的评分。

7.如权利要求5所述的基于反射的安卓应用微服务化系统,其特征在于,所述函数调用集生成模块包括:函数查找模块,用于查找所述目标对象从第一次出现到包含所述目标数据的过程中所有调用的函数以及所有以所述目标对象为参数的函数;

函数划分模块,依据运行时栈模型提供的函数调用栈信息,将查找到的函数划分成调用栈层次不完全相同但最后执行逻辑相同的多个函数调用集。

8.如权利要求5所述的基于反射的安卓应用微服务化系统,其特征在于,所述遍历模块在遍历时,实时记录当前引用链中已经使用的对象,如果遍历过程中遇到了已经使用过的对象,则跳过该对象。

说明书 :

基于反射的安卓应用微服务化方法及系统

技术领域

[0001] 本发明涉及计算机软件,尤其涉及一种基于反射的安卓应用微服务化方法及系统。

背景技术

[0002] 应用功能及数据的开放与融合能够产生巨大的价值,但安卓应用的大部分功能与数据并不提供可程序化调用的接口,难以实现功能及数据的开放与融合。目前,实现安卓应用功能及数据的开放与融合的最好办法是将安卓应用微服务化,即将安卓应用中的功能与数据以服务的形式提取出来。对于安卓应用来说,微服务化需要在应用运行时对应用进行修改。在经典软件工程中,强调的是在开发态修改软件,并不支持安卓应用微服务化的需求。而操作系统、中间件等系统软件能够提供计算反射(computational reflection,简称反射)机制,该机制能够实现对软件运行态的监测与控制。基于计算反射机制,能够有效解决安卓应用的微服务化问题。基于计算反射机制,通过监测应用运行时安卓系统的各种信息,生成安卓应用运行时的行为描述,对这些行为描述按需处理并生成应用控制逻辑,最终实现安卓应用的微服务化。
[0003] 然而,安卓应用的功能实现通常是非常复杂的,应用自身的包和所依赖的包一般数目巨大,这意味着实现功能的代码所依赖的函数数目可能很多,调用栈深度很深。行为反射技术框架所记录的执行序列是应用运行时除系统调用外的所有函数调用,所以执行序列的条目通常非常巨大,函数调用栈很深。这是执行序列复杂性的一方面体现。另一方面,由于执行序列中某一函数的构造可能存在多种方式,因此对于目标功能与数据可能存在多个运行时栈模型切片,每个切片对应一种微服务开发方法。每个切片可能是单线程也可能是多线程结构,不同结构的微服务开发方法也不相同。不同的切片生成微服务的难度有较大差别,这也是执行序列复杂性的体现。
[0004] 同时,对于某一特定的运行时栈模型切片,需要从目标结果或目标数据一步步反向构造能实现目标功能的代码片段。构造执行序列中的某条函数调用时,如果该函数的执行依赖一个新对象,就需要把从该对象第一次出现到该函数调用的所有的该对象调用的函数构造出来,这样才能保证该对象在该函数执行时的可用性和正确性。而在这一段执行序列中,该对象调用的函数有可能会依赖更多新的对象,又将重复上述过程,直至没有新对象依赖为止。整个过程产生了一个依赖关系树,从图8所示的目标函数依赖关系树可以看出,构造目标函数的调用可能涉及非常多的新对象及这些新对象的函数调用,这体现了运行时栈模型中数据依赖的复杂性。再者,在运行时栈模型中,有一部分对象是调用构造函数或者作为某个函数的返回值产生的,但还有一部分对象第一次出现就作为函数的参数或者调用者出现,对于这些对象,需要在运行时堆模型中获取。在运行时堆模型中获取对象,需要根据对象的引用信息,不断地寻找引用了对象的对象,直至寻找到一个静态对象。这一过程称为寻找对象引用链,对象引用链如图9所示,图中实线所连接的就是成功寻找到静态变量的引用链,虚线表示在路径中并未成功找到静态变量。找到静态变量后,有些静态变量的类加载器可能与应用类加载器(安卓应用最基础的类加载器)不一致,此时我们需要进一步去构造该静态变量的类加载器。这些过程体现出运行时堆模型中也存在着复杂的数据依赖。
[0005] 执行序列复杂和数据依赖复杂将导致根据行为反射运行时模型将安卓应用微服务化的学习成本非常高,开发过程也非常艰难与耗时。

发明内容

[0006] 本发明主要目的在于,提供一种基于反射的安卓应用微服务化方法及系统,以解决现有的将安卓应用微服务化的方式所遇到的执行序列复杂和数据依赖复杂的问题。
[0007] 本发明是通过如下技术方案实现的:
[0008] 一种基于反射的安卓应用微服务化方法,包括如下步骤:
[0009] 步骤S1:在安卓应用运行时,对所述安卓应用的运行进行监控,得到所述安卓应用的行为反射运行时模型,然后跳转至步骤S2;所述行为反射运行时模型包括运行时栈模型和运行时堆模型;
[0010] 步骤S2:标注所述运行时栈模型中包含目标数据的目标对象,然后跳转至步骤S3;
[0011] 步骤S3:生成所述目标对象的所有函数调用集,然后跳转至步骤S4;
[0012] 步骤S4:分析使用每一函数调用集生成函数调用代码的难度,并据此为每一函数调用集进行评分,然后跳转到步骤S5;
[0013] 步骤S5:判断被选择的函数调用集是否依赖新对象,当所述被选择的函数调用集依赖新对象时,跳转至步骤S2,并将依赖的新对象作为所述目标对象,否则跳转至步骤S6,所述被选择的函数调用集为根据各函数调用集的评分从所述所有函数调用集中选择的;
[0014] 步骤S6:将各次选择的函数调用集按序组成函数调用序列,并使用所述函数调用序列生成可执行的函数调用代码;
[0015] 步骤S7:对于无法在所述运行时栈模型中生成的目标对象,在所述运行时堆模型中,根据目标对象间的引用信息生成所述目标对象的所有引用链;
[0016] 步骤S8:判断被选择的目标对象引用链开头的静态对象的类加载器是否与应用类加载器一致,如果不一致,则将所述类加载器作为新的目标对象返回执行步骤S7,如果一致则执行步骤S9;
[0017] 步骤S9:根据被选择的目标对象引用链生成目标对象构造代码;
[0018] 步骤S10:将所述函数调用代码和目标对象构造代码包装成微服务接口。
[0019] 进一步地,所述步骤S4中,分析使用函数调用集生成函数调用代码的难度,并据此为该函数调用集进行评分的步骤包括:
[0020] 统计该函数调用集中函数调用的数目A;
[0021] 统计该函数调用集所依赖的新对象的数目B;
[0022] 统计该函数调用集所依赖的所有新对象的总相关函数调用的数目C;
[0023] 统计该函数调用集中无法在运行时栈模型中构造的新对象数目D;
[0024] 根据数目A、数目B、数目C及数目D各自的预设权重,将数目A、数目B、数目C及数目D进行加权求和,得到该函数调用集的评分。
[0025] 进一步地,所述步骤S3中,生成所述目标对象的所有函数调用集包括如下步骤:
[0026] 查找所述目标对象从第一次出现到包含所述目标数据的过程中所有调用的函数以及所有以所述目标对象为参数的函数;
[0027] 依据运行时栈模型提供的函数调用栈信息,将查找到的函数划分成调用栈层次不完全相同但最后执行逻辑相同的多个函数调用集。
[0028] 进一步地,所述步骤S7包括:
[0029] 步骤S7A:从目标对象开始,遍历引用了该目标对象的对象,并判断引用了该目标对象的对象的类型,所述类型包括基础数据类型对象、普通堆对象、类对象、数组对象和引用对象;
[0030] 步骤S7B:如果当前遍历到的对象不是一个类对象,则继续以此对象为新的目标对象进行下一轮遍历,如果当前遍历到的对象是一个类对象,查找该对象的一个静态成员变量,并根据所述静态成员变量与目标对象间的引用关系,得到目标对象的一条引用链;
[0031] 步骤S7C:重复步骤S7A和步骤S7B,直到得到所有以目标对象结尾,以所述静态成员变量开头的引用链。
[0032] 进一步地,执行所述步骤S7B时,实时记录当前引用链中已经使用的对象,如果遍历过程中遇到了已经使用过的对象,则跳过该对象。
[0033] 一种基于反射的安卓应用微服务化系统,包括:网构软件行为反射技术框架、目标对象标注模块、函数调用集生成模块、函数调用集评分模块、判断模块、函数调用代码生成模块、目标对象引用链生成模块、类加载器构造模块、目标对象构造代码生成模块和微服务化接口包装模块;
[0034] 所述网构软件行为反射技术框架,用于在安卓应用运行时,对所述安卓应用的运行进行监控,得到所述安卓应用的行为反射运行时模型,所述行为反射运行时模型包括运行时栈模型和运行时堆模型;
[0035] 所述目标对象标注模块,用于标注所述运行时栈模型中包含目标数据的目标对象;
[0036] 所述函数调用集生成模块,用于生成所述目标对象的所有函数调用集;
[0037] 所述函数调用集评分模块,用于分析使用每一函数调用集生成函数调用代码的难度,并据此为每一函数调用集进行评分;
[0038] 所述判断模块,用于判断被选择的函数调用集是否依赖新对象,当所述被选择的函数调用集依赖新对象时,返回运行所述目标对象标注模块,并将依赖的新对象作为所述目标对象,否则运行所述函数调用代码生成模块,所述被选择的函数调用集为根据各函数调用集的评分从所述所有函数调用集中选择的;
[0039] 所述函数调用代码生成模块,用于将各次选择的函数调用集按序组成函数调用序列,并使用所述函数调用序列生成可执行的函数调用代码;
[0040] 所述目标对象引用链生成模块,用于根据目标对象间的引用信息生成所述目标对象的所有引用链;
[0041] 所述类加载器构造模块,用于判断被选择的目标对象引用链开头的静态对象的类加载器是否与应用类加载器一致,如果不一致,则将所述类加载器作为新的目标对象返回运行所述目标对象引用链生成模块;
[0042] 所述目标对象构造代码生成模块,用于根据被选择的目标对象引用链生成目标对象构造代码;
[0043] 所述微服务化接口包装模块,用于将所述函数调用代码和目标对象构造代码包装成微服务接口。
[0044] 进一步地,所述函数调用集评分模块包括:
[0045] 统计模块,用于统计函数调用集中函数调用的数目A、该函数调用集所依赖的新对象的数目B、该函数调用集所依赖的所有新对象的总相关函数调用的数目C,以及该函数调用集中无法在运行时栈模型中构造的新对象数目D;
[0046] 加权求和模块,用于根据数目A、数目B、数目C及数目D各自的预设权重,将数目A、数目B、数目C及数目D进行加权求和,得到该函数调用集的评分。
[0047] 进一步地,所述函数调用集生成模块包括:
[0048] 函数查找模块,用于查找所述目标对象从第一次出现到包含所述目标数据的过程中所有调用的函数以及所有以所述目标对象为参数的函数;
[0049] 函数划分模块,依据运行时栈模型提供的函数调用栈信息,将查找到的函数划分成调用栈层次不完全相同但最后执行逻辑相同的多个函数调用集。
[0050] 进一步地,所述目标对象引用链生成模块包括遍历模块、引用链生成子模块;
[0051] 遍历模块用于从目标对象开始,遍历引用了该目标对象的对象,并判断引用了该目标对象的对象的类型,所述类型包括基础数据类型对象、普通堆对象、类对象、数组对象和引用对象,并在当前遍历到的对象不是一个类对象,则继续以此对象为新的目标对象进行下一轮遍历;
[0052] 引用链生成子模块用于在遍历模块当前遍历到的对象是一个类对象时,查找该对象的一个静态成员变量,并根据所述静态成员变量与目标对象间的引用关系,得到目标对象的一条引用链,并返回运行所述遍历模块,直到得到所有以目标对象结尾,以所述静态成员变量开头的引用链。
[0053] 进一步地,所述遍历模块在遍历时,实时记录当前引用链中已经使用的对象,如果遍历过程中遇到了已经使用过的对象,则跳过该对象。
[0054] 与现有技术相比,本发明提供的基于反射的安卓应用微服务化方法及系统,通过对安卓应用运行进行监控,得到应用的行为反射运行时模型,并在其中的运行时栈模型中标注包含目标数据的目标对象,生成目标对象的所有函数调用集,再根据使用函数调用集生成函数调用代码的难度为每一函数调用集进行评分,并根据评分推荐函数调用集以生成可执行的函数调用代码。对不能在运行时栈模型中生成的目标对象,在运行时堆模型中生成目标对象的所有引用链,并构造类加载器,再根据被选择的目标对象引用链生成目标对象构造代码,最后再将生成的函数调用代码和目标对象构造代码结合起来包装成微服务接口。本发明能大大减少开发安卓应用微服务的时间,有效解决安卓应用微服务开发中执行序列复杂与数据依赖复杂两大难题。

附图说明

[0055] 图1是基于反射的安卓应用微服务化开发主要流程;
[0056] 图2是基于反射的安卓应用微服务化开发方法具体流程
[0057] 图3是本发明实施例提供的基于调用栈和依赖路径的函数调用代码生成方法流程示意图;
[0058] 图4:网构软件行为反射技术框架示意图;
[0059] 图5:运行时栈模型的构造流程示意图;
[0060] 图6:运行时堆模型的构造流程示意图;
[0061] 图7:代码运行支持子系统构造示意图;
[0062] 图8:目标函数依赖关系树示意图;
[0063] 图9:对象引用链示意图;
[0064] 图10:本发明实施例提供的基于调用栈和依赖路径的函数调用代码生成系统组成示意图;
[0065] 图11:本发明实施例提供的基于对象引用链的对象构造代码生成方法流程示意图;
[0066] 图12:本发明实施例提供的基于对象引用链的对象构造代码生成系统组成示意图;
[0067] 图13:本发明实施例提供的基于反射的安卓应用微服务化方法流程示意图;
[0068] 图14:本发明实施例提供的基于反射的安卓应用微服务化系统组成示意图。

具体实施方式

[0069] 为使本发明的目的、技术方案和优点更加清楚明白,下面结合实施例和附图,对本发明作进一步详细说明。
[0070] 如图1所示,基于反射的安卓应用微服务化开发主要流程包括:
[0071] 1.获取安卓应用原始运行时模型:通过网构软件行为反射技术框架1,对安卓应用功能的运行进行监控,获取安卓应用的行为反射运行时模型,包括运行时堆模型和运行时栈模型。
[0072] 2.模型转换:将获取到的运行时堆模型和运行时栈模型,转换成与功能相关的函数调用和对象。原始的运行时堆模型和运行时栈模型记录的是应用功能运行时所有发生的非系统函数调用序列和所有堆上对象,其中大部分是与功能无关的,因此需要将与功能相关的部分抽离出来。模型转换主要完成三项工作。对于运行时栈模型,用户选定目标函数调用或目标对象后,通过函数调用栈生成所有有关该函数或对象的函数调用集,然后对每个函数调用集给出评分,以评价使用该调用集生成代码的难度与可行性。这一流程会重复若干次,直至所有选出的函数调用集里不再依赖新的对象。对于运行时堆模型,用户选定目标对象之后,通过对象引用信息生成对象及其类加载器的引用链,其源头是某个静态对象。
[0073] 3.代码生成:将模型转换获得的函数调用集和对象引用链转换成可执行的Java代码。通过整合若干轮次中选择的函数调用集,将它们按照运行时堆模型中对应执行序列的顺序整理排序,并生成可执行代码。同时,根据引用链构造出对象及其类加载器代码,并对于引用链中的特殊类型对象进行处理优化,以保证构造代码的可用性。
[0074] 4.形成安卓应用微服务接口:将两部分代码整合,并封装形成安卓应用微服务接口。该步骤最后形成安卓应用微服务接口,通过将两部分代码整合,形成一份完整代码,通过将输入和输出转化成参数和返回值,将代码封装成接口,至此,完整生成了安卓应用某项功能的微服务,实现了安卓应用的微服务化。
[0075] 将上述4步细化后,基于反射的安卓应用微服务化开发方法具体流程如图2所示,包括如下步骤:
[0076] 1)通过网构软件行为反射技术框架1获取应用的行为反射运行时模型[0077] 首先启动网构软件行为反射技术框架1对安卓应用进行监控,并在应用上实际操作,使应用完成需要的功能,手机屏幕呈现出需要的数据。此时结束对应用的监控,并从该框架中导出应用的行为反射运行时模型,行为反射运行时模型包括运行时栈模型和运行时堆模型。
[0078] 2)标注运行时栈模型中的目标对象
[0079] 最终目标是获取到目标功能执行完后得到的数据,而数据是包含在对象之中的,因此需要在运行时栈模型中标注包含其所需要数据的目标对象。
[0080] 3)生成目标对象的所有函数调用集
[0081] 将目标对象从第一次出现到包含目标数据过程中所有调用的函数及所有以该对象为参数的函数找到,并依据运行时栈模型提供的函数调用栈信息,将这些函数调用划分成调用栈层次不完全相同但最后执行逻辑相同的多个函数调用集。每个函数调用集都有可能进一步生成目标对象构造代码。
[0082] 4)函数调用集评分与选择
[0083] 对于之前获得的每一个目标对象函数调用集,根据函数调用依赖的新对象个数、新对象是否为全局变量等特征,给函数调用集一个评分,评分代表着对该函数调用集生成代码难度的判断。根据函数调用集评分选择一个函数调用集作为代码生成的一部分函数调用。选择完成后,如果函数调用集中存在依赖的新对象,需要将新对象作为新的目标对象,重复步骤二到步骤四,直至不依赖新的对象。
[0084] 5)堆对象引用链生成
[0085] 运行时栈模型中生成的函数调用集可能依赖新对象,而新对象可能无法在运行时栈模型中构造。当对象第一次在运行时栈模型中出现并不是调用构造函数或作为某个函数调用的返回值时,该对象就需要在运行时堆模型中生成。遍历引用了目标对象的对象列表,并将其中每个对象作为新的目标对象继续遍历引用,如果当前目标对象是一个静态对象,则停止对当前对象的引用遍历,得到初始目标对象的所有引用链。
[0086] 6)引用链选择及类加载器生成
[0087] 对于之前生成的每一条目标对象的引用链,按链中对象个数从少到多列出方案。选定一条引用链后,判断引用链开头的静态对象的类加载器是否与应用类加载器一致。如果该类加载器与应用类加载器不一致,将其作为一个新的目标对象再次执行步骤五到步骤六。
[0088] 7)选定方案的代码生成
[0089] 之前步骤中,对于包含目标数据的对象,基于运行时栈模型,通过若干轮执行和选择,得出了若干函数调用集;对于函数调用集中依赖的不能在运行时栈模型中生成的对象,基于运行时堆模型和选择的目标对象得出了对象的引用链及引用链头部静态对象的类加载器。对于这些选定的函数调用和对象,将它们按序组合,并按照Java的代码规则将其转换为可执行的Java代码。
[0090] 8)包装微服务接口
[0091] 将生成的代码进行处理,将输入和代码中依赖的数字与字符串抽象成微服务接口调用参数,将获得的目标数据抽象成微服务接口的返回值,生成一个完整的安卓应用功能的微服务接口。
[0092] 由上述说明可以看出,安卓应用微服务化基于网构软件行为反射技术框架1,主要包括两部分,分别针对行为反射运行时模型中的运行时栈模型和运行时堆模型。对于运行时栈模型的微服务代码生成,目标是快速定位到所需要的目标对象或函数调用,并为其推荐目标函数调用的生成方案,进而生成部分代码,为此,本发明提出基于调用栈和依赖路径的函数调用代码生成方法及系统。而对于运行时堆模型的微服务代码生成,目标则是快速生成目标对象的所有函数引用链方案,进而生成部分代码,为此,本发明提出了基于对象引用链的对象构造代码生成方法及系统。
[0093] 对于运行时栈模型的微服务代码生成,需要将一个能够实现目标功能、获取目标数据的函数调用序列从栈模型中抽离出来。如图3所示,本发明实施例提供的基于调用栈和依赖路径的函数调用代码生成方法,包括如下步骤:
[0094] 步骤S1:在安卓应用运行时,对安卓应用的运行进行监控,得到安卓应用的行为反射运行时模型,然后跳转至步骤S2;行为反射运行时模型包括运行时栈模型和运行时堆模型;
[0095] 步骤S2:标注运行时栈模型中包含目标数据的目标对象,然后跳转至步骤S3;
[0096] 步骤S3:生成目标对象的所有函数调用集,然后跳转至步骤S4;
[0097] 步骤S4:分析使用每一函数调用集生成函数调用代码的难度,并据此为每一函数调用集进行评分,然后跳转到步骤S5;
[0098] 步骤S5:判断被选择的函数调用集是否依赖新对象,当被选择的函数调用集依赖新对象时,跳转至步骤S2,并将依赖的新对象作为目标对象,否则跳转至步骤S6,被选择的函数调用集为根据各函数调用集的评分从所有函数调用集中选择的;
[0099] 步骤S6:将各次选择的函数调用集按序组成函数调用序列,并使用函数调用序列生成可执行的函数调用代码。
[0100] 对上述各步骤详述如下:
[0101] 在步骤S1中,通过网构软件行为反射技术框架1对安卓应用的运行进行监控,以得到安卓应用的行为反射运行时模型。
[0102] 如图4所示,网构软件行为反射技术框架1(以下简称框架1)首先实现了一个行为解释器,用于生成应用的行为自述,称为应用的行为反射运行时模型。应用的执行可以视为编程语言框架的堆栈操作,应用方法的执行与返回,相当于编程语言框架的栈操作;应用对象的修改,相当于编程语言框架的堆操作。通过这一解释器,能够生成对应应用方法的执行序列和对应应用对象的堆文件。其次,该框架1提出了一套基于行为反射运行时模型生成对应用进行指令级控制的方法。这一方法先要将原始的行为模型转成适合操作的活动序列,再按照应用的控制需求将需要的活动序列组合起来,最后将其翻译为可执行的代码片段,形成指令级控制方法。最后,该框架1实现了一个支持控制安卓应用的引擎。该引擎可以在不对已有安卓应用字节码文件做任何修改的前提下,在安卓应用上执行之前形成的指令级控制方法。以安卓应用的某一功能与数据为例,首先开启框架1对该应用的监控,并在应用内实际操作,达成该功能,当目标结果或数据呈现出来之后,关闭对于该应用的监测。此时得到了框架1开启到关闭这个时段内该应用的行为反射运行时模型,将模型中适合操作的活动序列筛选出来,并进一步筛选出与该功能和数据相关的的活动序列,将其按微服务化的需求适当挑选组合,并翻译成可执行的代码片段,这样就形成了该应用该功能所对应的微服务。
[0103] 安卓应用在运行时,可以视为一个或多个进程,安卓系统会将应用需要的可执行文件加载到内存中。安卓进程所占内存分为三部分:代码段、堆区和栈区。在Java中,栈区用于存储局部变量,当线程调用某方法时,会申请一个帧,帧中保存着方法的调用者、参数、返回值类型等等信息;堆区用于进程动态分配内存和存储全局变量,线程创建新对象时相当于申请一块堆区内存。安卓应用运行时会引起栈区和堆区的内存数据变化,因此安卓应用的行为反射运行时模型需要反映安卓应用在运行时段内代码的执行情况,代码的执行情况对应着栈区的内存数据变化。同时还要反映安卓应用在运行时段内对象的创建、修改、删除,对象的创建、修改、删除对应着堆区的内存数据变化。
[0104] 行为反射运行时模型包括运行时栈模型和运行时堆模型。运行时栈模型由多条控制流组成,控制流的顺序取决于控制流图,每个控制流对应于一个Java线程的执行序列。运行时堆模型由一组内存数据初始值和一段时间内的内存修改活动记录组成,其中也记录了每个内存位置对象的类、引用、域等等信息。通过分析运行时栈模型,能够了解安卓应用运行时任意时刻的代码执行情况;而通过分析运行时堆模型,能够了解代码执行时所依赖的对象的数据状态。
[0105] 在构造上,运行时栈模型包含了控制流图、运行时发生的活动、发生的活动的关系,运行时发生的活动可以视为栈模型的节点,发生的活动的关系可以视为栈模型的边。具体来说,如图5所示,运行时栈模型的构造流程主要包括以下步骤:
[0106] 1)生成控制流图:
[0107] 由于安卓应用会混淆中间代码,中间代码会通过应用运行时环境加载执行,因此框架1采用修改应用运行时环境的方法来获取应用的中间代码,获取中间代码的好处是易于开发,且能保证与执行活动的一致,保障了控制流图能匹配运行时的控制流。
[0108] 2)按需重配置控制流图:
[0109] 框架1提出了一个适用于程序执行监测的行为解释器,只需按需求设置模型粒度配置,行为解释器就能将需要监测的控制流图放入自身执行。
[0110] 3)行为解释器生成应用运行时活动:
[0111] 由于指令的数目非常巨大,若将每条指令对应于一个活动,亦即对应于栈模型中的一个节点,会导致指令序列规模巨大且难以处理。因此,框架1将活动分为数值计算、方法调用、分支控制等多种类型,并在行为解释器中加入支持多粒度筛选的活动筛选器,用于生成栈模型节点。
[0112] 4)生成控制流之间的依赖关系:
[0113] 并发编程中的线程同步和线程唤醒(即线程依赖关系),可以抽象为栈模型中节点之间的边。框架1对多种线程依赖关系进行了分类,并对他们进行处理,生成栈模型中节点之间的边。
[0114] 运行时栈模型中包含了应用运行时的函数执行,其可视化结构中除了读或写对象的域之外,其它函数调用的格式都是统一的。一条函数调用顺序标注了其返回值类型、调用者类型、函数名称、各个参数的类型。每条函数调用还包含了详细信息,从上到下的顺序依次是调用者的类型及地址、每个参数的类型和地址、前两层调用栈对应的函数(表明当前函数是在哪个函数内部调用的)、函数返回值类型和地址。对于基础数据类型,模型用它们的值替代了类型和地址。运行时栈模型除了给出函数调用的详细信息和顺序之外,还给出了函数之间的关系。其可视化结构中每条函数前的缩进代表着函数的层次。一个函数调用,其内部是由多条函数调用组成的,在运行时栈模型中,相邻两层的函数调用即体现了这样的关系。这样,整个函数调用序列实际上就是一个巨大的函数调用栈,每个函数调用都可以通过调用栈追溯到最深层的调用信息。
[0115] 如图6所示,在构造上,运行时堆模型包含了堆区的初始状态描述和运行时段内所有影响堆区数据的活动,结合这两种描述,可以获得堆区在应用运行时任意时刻任意地址的数据状态。如图6所示,运行时堆模型的构造流程主要包括以下步骤:
[0116] 1)生成堆区初始状态:
[0117] 堆区的初始状态可以视为应用开始运行时刻堆区数据的快照,如果在生成快照时,有别的线程对堆区进行修改,就会破坏初始状态的原子性。因此,框架1给出了一种描述堆区初始状态的BNF表示,并在生成堆初始状态时采用冻结堆数据的方法,保证原子性。
[0118] 2)生成堆区操作活动:
[0119] 堆区操作有两种,一是Java的垃圾回收器产生的回收内存的活动,二是对象域值的修改及新对象的分配,这部分操作在栈模型中有记录。实际开发过程中,只关注部分类和方法的执行,如果将每个影响堆区数据的操作都记录下来,会导致堆模型过大,不利于开发。因此框架1扩展了栈模型中的活动描述,使其支持描述垃圾回收活动,并提供多种粒度的筛选选项。
[0120] 3)查询堆对象状态:
[0121] 利用上面两种信息,即堆区初始状态和堆区操作活动,框架1设计了一个基于时间戳的堆对象状态查询算法,能够查询堆对象在任意时刻的状态。
[0122] 运行时堆模型中记录的是网构软件行为反射技术框架1对安卓应用开始监控时刻的整个内存的数据状态。由于开始监控时应用可能已经处于运行状态,因此运行时栈模型中有的对象在第一次出现之前就已经创建好了。运行时堆模型中记录的对象数据状态是对运行时栈模型很好的补充。
[0123] 运行时堆模型记录了所有的已创建的对象,运行时栈模型记录了该对象在内存中的位置,并记录了该对象的类型;接着记录了该对象的所有非静态成员变量,包括成员变量的名称,以及每个变量的当时的对象或值;最后记录了有哪些对象的某一成员变量是该对象。每个对象都有类型,运行时堆模型也记录了各种类的信息,首先记录了该类的父类,并记录了该类的类加载器对象信息;之后记录了该类的非静态成员变量名称;最后记录了该类的所有静态成员变量的名称,以及每个变量当时的对象或值。
[0124] 通过运行时堆模型记录的对象信息,可以充分了解行为反射技术框架1开始对应用进行监控时应用已有对象的详细数据状态,以及对象之间相互的引用关系。这为在堆模型中构造对象提供了基础。
[0125] 在生成了应用的行为反射运行时模型后,框架1提出了如何基于行为反射运行时模型为应用生成指令级控制。行为反射运行时模型中包含了一组有序的指令级别的活动,因此对行为反射运行时模型的操作就对应着对这组活动序列的增删改操作。框架1提出了控制的两种分类:行为式控制和结构式控制。行为式控制要求在不生成新代码、不重编译和重启应用的情况下,直接对原应用的状态进行控制修改。对于行为式控制,框架1对对象实例化、对象读写和函数调用三种情况提出了具体的控制实现。结构式控制则会将对运行时活动的修改体现到原应用的代码段当中。由于要保持等价性,框架1提出了一种较为灵活的结构式控制,即面向对象的堆控制等价代码片段。为了实现指令级控制,有两个需要考虑的两个关键问题,即基于活动序列的对象构造和基于运行时堆模型的对象构造。框架1给出了这两种对象的具体构造流程,并指出了如何将构造好的对象转换为可运行的代码。
[0126] 基于之前的模型设计与技术分析,该框架1实现了一个原型系统,该原型系统的全称是Reflection at low level interpreter,这个名字具有两层含义,一代表着其反射基于底层的行为解释器,二代表其可以监测控制所有级别的应用行为。这一原型系统对于广泛使用的安卓应用在应用行为的监测和控制上十分有效。该原型系统分为三个部分,分别是行为反射运行时模型构造子系统、模型分析与代码生成子系统和代码运行支持子系统。行为反射运行时模型构造子系统是基于行为反射运行时模型的构造方法(包括运行时栈模型的构造流程和运行时堆模型的构造流程)实现的,模型分析与代码生成子系统是基于为应用生成指令级控制的方法实现的,其技术细节已大致介绍完成。如图7所示,代码运行支持子系统亦是整个框架1的重要组成部分,代码运行支持子系统能够支持生成的控制代码的运行,其在安卓系统的框架层上添加了行为反射类加载器。成的控制代码会编译生成Dex字节码文件,当对应应用启动时,行为反射类加载器会加载该字节码文件至应用进程。同时,应用安卓的Binder机制向接口管理进程注册控制代码中的互操作接口。这样,用户便可通过互操作接口对应用实现控制。
[0127] 对于运行时栈模型,最终目标是从中获取能得到目标数据的完整的不依赖新对象的函数调用序列。步骤S2中,目标数据最终是在某条函数调用的返回对象中的,因此需要构造最终的函数调用。但是,标注一个函数调用体验是非常差的,因为函数调用的定义很长,不利于输入。构造函数调用,实质上是在构造该函数的调用者和参数,即若干个对象;为目标函数生成相关的函数调用集,实质上就是为目标函数调用用到的对象生成相关的函数调用集,这两者是等价的。由于对象与地址是一一对应的,标注对象时只需要输入地址即可,与标注函数调用相比,标注对象更为简单直观,因此在生成目标数据时统一用对象地址作为输入。
[0128] 对于步骤S3,为了能成功执行运行时栈模型中的某条函数调用,需要构造出该函数调用需要的对象。构造出的对象的每个域值必须与应用在实际调用该函数时所用到对象的域值保持一致。想要达到这一目标,需要在构造对象时复现对象所经历的每一步操作,采用的思路是将目标对象从第一次出现到该函数调用过程中所有调用的函数以及以目标对象为参数的所有函数调用找出,并在不出现冲突的情况下将这些函数调用全部加入待构造集合。具体来说,在步骤S3中,生成目标对象的所有函数调用集包括如下步骤:
[0129] 查找目标对象从第一次出现到包含目标数据的过程中所有调用的函数以及所有以目标对象为参数的函数;
[0130] 依据运行时栈模型提供的函数调用栈信息,将查找到的函数划分成调用栈层次不完全相同但最后执行逻辑相同的多个函数调用集。
[0131] 某一对象调用函数或作为参数执行函数调用的过程中,该对象的域值可能并不会被修改,但当该对象的阈值被修改时,运行时栈模型中一定会存在一条关于该对象的WriteField函数调用。将目标对象的所有相关函数找出并加入待构造集合虽然会产生一定冗余,但是能保证对象在被目标函数调用时,其数据状态一定是正确的,因此可采用这一思路来生成调用集合。
[0132] 通过对运行时栈模型的所有函数调用及函数调用的细节描述的遍历,可以找到所有截止目标函数调用的关于目标对象的函数调用。在寻找关于目标对象的函数调用时,由于ReadField函数代表的是对该对象某个域的读取,其并不影响对象的数据状态,因此在寻找过程中会将ReadField函数过滤掉。在所有目标对象的相关函数调用中,目标对象的类型不尽相同,这是由于其中一些类型是接口,另一些类型是实现了接口的类;或者是由于其中一些类型是父类,另一些类型是继承了父类的子类。无论是哪种情况,在后序生成代码时只需要按照函数调用描述中的类型来操作,都不会导致代码出错。
[0133] 得到目标对象的所有函数调用之后,需要将这些函数调用整理成不同的函数调用集。并不是所有函数调用都能加入同一个函数调用集中,因为函数调用之间存在包含关系。如下给出了生成目标对象所有函数调用集的伪代码。
[0134]
[0135] 挑选一个函数调用集时,对于一个待挑选的函数,如果挑选了这一函数调用,则该函数内部的所有函数都不能挑选,因为其函数栈下所有的函数调用都是都是由其本身的调用产生的;如果不挑选该函数,则必须将该函数函数栈内下一层的所有函数调用完整挑选,即对下一层的所有函数都执行这一挑选逻辑,这保证了不挑选该函数的挑选结果与挑选该函数的挑选结果对目标对象的数据状态影响是等价的。根据这样的挑选逻辑,能够生成所有完整反映对象数据状态变化的函数调用集,这些函数调用集对于对象的数据状态改变是等价的。
[0136] 生成函数调用集的目的是完整描述成功执行目标函数调用所需要用到的函数执行逻辑,因此可用的函数调用集应该包含最后的目标函数调用,即使这一调用并不是一个顶层调用。如果不包含目标函数调用,即之前得到的所有函数调用中的最后一条,该函数调用集能够实现应用的目标功能,但是无法取出功能执行完后的目标数据。筛选掉不包含目标函数调用的函数调用集,最终得到的函数调用集将进行进一步评分。
[0137] 由于在运行时栈模型中生成目标数据相关的函数调用会经历若干轮目标对象的函数调用集生成,除了第一轮函数调用集生成,之后生成的函数调用集可能会与之前的有重复函数调用。为了避免重复的函数调用,在生成目标对象的所有函数调用集时,将每一轮的目标对象及被选择的函数调用集所用到的函数序号存储在一个集合当中,在获取依赖的新对象的所有调用函数时,如果遇到一条集合中存在的函数调用,则跳过对该函数调用及其函数调用栈下所有函数的搜索。
[0138] 对于步骤S4,为目标对象生成的函数调用集一般数目很多,而函数调用集依赖的新对象会决定之后函数调用集生成以及代码生成的难度。应选取到生成代码可能性高且难度低的函数调用集,使得用最终函数调用方案生成的代码有较高的可用性。因此,本发明实施例还设计了评价函数调用集生成代码难度的一套子方法,为每个函数调用集生成一个评分。分析使用函数调用集生成函数调用代码的难度,并据此为该函数调用集进行评分的步骤包括:
[0139] 统计该函数调用集中函数调用的数目A;
[0140] 统计该函数调用集所依赖的新对象的数目B;
[0141] 统计该函数调用集所依赖的所有新对象的总相关函数调用的数目C;
[0142] 统计该函数调用集中无法在运行时栈模型中构造的新对象数目D;
[0143] 根据数目A、数目B、数目C及数目D各自的预设权重,将数目A、数目B、数目C及数目D进行加权求和,得到该函数调用集的评分。
[0144] 为了给每个函数调用集生成评分,需要统计函数调用集中与代码生成相关的特征数据,并给每个特征加权,形成每个特征的评分。选取函数调用集中的以下4个特征作为评分生成依据:
[0145] 1)函数调用集中函数调用的数目
[0146] 对于一个函数调用集合,函数调用的数目越少,其生成代码的可用性就越高,难度也可能较低。由所有函数调用集的生成方式可知,所有函数调用都是最外层调用的函数调用集一定是函数调用数目最少的。函数调用集中函数调用数目较少,大多数时候意味着其中较多调用的函数调用栈层数较浅。在其他条件相同的情况下,包含目标对象的一条函数调用是比这条函数调用内部包含目标对象的所有函数调用要好的,其生成的代码可用性也更高,因为生成一条调用对应代码比生成多条调用对应代码出错的概率要小,而且函数内部还有不包含目标对象的函数调用,执行内部包含目标对象的所有函数调用并不能完整等价该函数的执行。同时,相同条件下,函数调用数目更少意味着代码生成量更少,生成难度更低。
[0147] 2)函数调用集所依赖的新对象的数目
[0148] 一个函数调用集可能会依赖若干新对象,依赖的新对象的数目越少,其生成代码的难度可能越低。对于函数调用集依赖的每个新对象,需要将它们作为新的目标对象,进行新的一轮函数调用集生成、评分与选择,因此更少的新对象依赖意味着更少的对象函数调用集操作轮次,开发时间更短。同时,依赖的新对象少,之后的操作轮次潜在依赖的新对象也有较高概率很少,生成代码难度有较高概率很低。
[0149] 3)函数调用集所依赖的所有新对象的总相关函数调用的数目
[0150] 对于某个函数调用集,其中的每个新对象都需要作为目标对象进行新一轮操作,这些新对象的总相关函数调用数目越少,之后生成的函数调用集方案就越少,每个函数调用集所包含的函数调用数目也可能越少。新对象相关的函数调用数目很大程度上能反映下一轮函数调用集生成代码的难度,因此,一个函数调用集的新对象相关函数调用数目越少,其生成代码的难度可能越低。
[0151] 对于每条函数调用所依赖的新对象,可以统计其从第一次出现到该条函数调用的所有相关函数调用,这里用到的方法和对象调用集生成时获取相关函数调用的方法是一致的。由对象调用集生成部分的分析可知,对象所有相关函数调用不能全部执行,需要将其划分成函数调用集。因此,采用一种简单的思路,其伪代码如下所示:
[0152]
[0153] 在统计对象相关函数调用时,当某条函数的参数或者调用者是该对象时,不继续遍历其调用栈下更深层的函数。这相当于生成了一个全是最外层调用的函数调用集,将其函数调用数目作为对象的相关函数调用数目。这样做不需要遍历整个函数调用栈,能快速高效地获取对象的相关函数调用数目。
[0154] 得出了每条函数调用所依赖的对象的相关函数调用数目之后,可以统计每个函数调用集依赖的所有新对象的相关函数调用数目总和,其伪代码如下所示:
[0155]
[0156]
[0157] 由于不同的函数调用所依赖的新对象可能相同,统计时应避免重复,而某一对象在调用集中靠后的函数中所统计的相关函数调用数目比其在靠前函数中统计的调用数目大,因为相比靠前的位置,靠后位置处对象肯定执行了同等或更多的相关函数调用。在统计时,遇到相同的对象,只需将更大的相关函数调用数目替换之前的值即可得到正确值。将所有新对象的相关函数调用数目求和,即得到了函数调用集的总相关函数调用数。
[0158] 4)函数调用集中无法在运行时栈模型中构造的新对象数目
[0159] 当一个对象在运行时栈模型中第一次出现就作为函数调用的参数或调用者时,这个对象就不能只依靠运行时栈模型来构造。能够成功通过运行时栈模型构造的对象只有两种:通过构造函数生成的对象和作为某个函数返回值的对象。不能只通过运行时栈模型构造的对象还需要通过运行时堆模型构造,这就需要额外生成代码,因此无法构造的对象越少,生成代码的难度越低。在获取某对象的所有相关函数时,对于第一条函数调用,判断其是否是该对象的构造函数,或者其返回值是否是该对象。由此,可以获取函数调用集中无法再运行时栈模型中构造的新对象数目。
[0160] 根据以上描述的四个特征,为每个函数调用集生成一个评分,由以上说明可知,评分越高代表生成代码的难度越高,评分越低代表生成代码的难度越低。因此,在跳转到步骤S5之前,可按照函数调用集评分由低到高的顺序推荐函数调用集以供选择。选择一个函数调用集后,给出需要进一步构造的依赖对象,需要再次将这些对象作为目标对象转换成函数调用集。
[0161] 当选定的函数调用集不再依赖新对象时,将各轮选择的函数调用集按序整理成一个函数调用序列。除了在运行时栈模型中无法生成的对象外,这一函数调用序列完整地反映了安卓应用对应功能的执行。对于这一序列,将自动生成可执行的Java代码。最后一行生成代码即可得到目标数据对象,而对于如第一行生成代码一样不能在运行时栈模型中生成的对象,将对象的地址写入代码,这部分代码不能运行,需要进一步在运行时堆模型中构造该对象,并在为对象生成代码后将此部分代码替换。如果选定的函数调用集还依赖新对象,则跳转到步骤S2,并将依赖的新对象作为新的目标对象,重复执行步骤S2至步骤S5,直到选定的函数调用集不再依赖新对象时再跳转到步骤S6。
[0162] 基于上述基于调用栈和依赖路径的函数调用代码生成方法,本发明实施例还提供了一种基于调用栈和依赖路径的函数调用代码生成系统,如图10所示,该系统包括网构软件行为反射技术框架1、目标对象标注模块2、函数调用集生成模块3、函数调用集评分模块4、判断模块5和函数调用代码生成模块6;
[0163] 网构软件行为反射技术框架1,用于在安卓应用运行时,对安卓应用的运行进行监控,得到安卓应用的行为反射运行时模型,行为反射运行时模型包括运行时栈模型和运行时堆模型;
[0164] 目标对象标注模块2,用于标注运行时栈模型中包含目标数据的目标对象;
[0165] 函数调用集生成模块3,用于生成目标对象的所有函数调用集;
[0166] 函数调用集评分模块4,用于分析使用每一函数调用集生成函数调用代码的难度,并据此为每一函数调用集进行评分;
[0167] 判断模块5,用于判断被选择的函数调用集是否依赖新对象,当被选择的函数调用集依赖新对象时,返回运行目标对象标注模块2,并将依赖的新对象作为目标对象,否则运行函数调用代码生成模块6,被选择的函数调用集为根据各函数调用集的评分从所有函数调用集中选择的;
[0168] 函数调用代码生成模块6,用于将各次选择的函数调用集按序组成函数调用序列,并使用函数调用序列生成可执行的函数调用代码。
[0169] 函数调用集评分模块4包括:
[0170] 统计模块,用于统计函数调用集中函数调用的数目A、该函数调用集所依赖的新对象的数目B、该函数调用集所依赖的所有新对象的总相关函数调用的数目C,以及该函数调用集中无法在运行时栈模型中构造的新对象数目D;
[0171] 加权求和模块,用于根据数目A、数目B、数目C及数目D各自的预设权重,将数目A、数目B、数目C及数目D进行加权求和,得到该函数调用集的评分。
[0172] 基于调用栈和依赖路径的函数调用代码生成系统还包括:
[0173] 函数调用集推荐模块,用于按照函数调用集评分由低到高的顺序推荐函数调用集以供选择。
[0174] 函数调用集生成模块3包括:
[0175] 函数查找模块,用于查找目标对象从第一次出现到包含目标数据的过程中所有调用的函数以及所有以目标对象为参数的函数;
[0176] 函数划分模块,依据运行时栈模型提供的函数调用栈信息,将查找到的函数划分成调用栈层次不完全相同但最后执行逻辑相同的多个函数调用集。
[0177] 函数调用集生成模块3在生成目标对象的所有函数调用集时,将每一轮的目标对象及被选择的函数调用集所用到的函数序号存储在一个集合当中,并在获取依赖的新对象的所有调用函数时,如果遇到一条集合中存在的函数调用,则跳过对该函数调用及其函数调用栈下所有函数的搜索。
[0178] 该基于调用栈和依赖路径的函数调用代码生成系统中的各模块与基于调用栈和依赖路径的函数调用代码生成方法中的各步骤一一对应,用以执行基于调用栈和依赖路径的函数调用代码生成方法中的各步骤,各模块的具体工作原理及过程可参照上述基于调用栈和依赖路径的函数调用代码生成方法中的各步骤,在此不再赘述。
[0179] 对于无法在运行时栈模型中生成的目标对象,在运行时堆模型中,通过基于对象引用链的对象构造代码生成方法来生成对象构造代码。如图11所示,本发明实施例提供的基于对象引用链的对象构造代码生成方法,包括如下步骤:
[0180] 步骤S7:对于无法在运行时栈模型中生成的目标对象,在运行时堆模型中,根据目标对象间的引用信息生成目标对象的所有引用链;
[0181] 步骤S8:判断被选择的目标对象引用链开头的静态对象的类加载器是否与应用类加载器一致,如果不一致,则将类加载器作为新的目标对象返回执行步骤S7,如果一致则执行步骤S9;
[0182] 步骤S9:根据被选择的目标对象引用链生成目标对象构造代码。
[0183] 其中,步骤S7包括:
[0184] 步骤S7A:从目标对象开始,遍历引用了该目标对象的对象,并判断引用了该目标对象的对象的类型,类型包括基础数据类型对象、普通堆对象、类对象、数组对象和引用对象;
[0185] 步骤S7B:如果当前遍历到的对象不是一个类对象,则继续以此对象为新的目标对象进行下一轮遍历,如果当前遍历到的对象是一个类对象,查找该对象的一个静态成员变量,并根据静态成员变量与目标对象间的引用关系,得到目标对象的一条引用链;
[0186] 步骤S7C:重复步骤S7A和步骤S7B,直到得到所有以目标对象结尾,以静态成员变量开头的引用链。
[0187] 对于步骤S7,需要从运行时堆模型中获取某些对象的信息,并根据信息构造出这些对象。因此应辅助构造出其选定的对象。在Java中,一个类的静态成员变量是可以通过直接调用生成的,不需要依赖其他任何条件。以此为基础,需要寻找到某个类的静态成员变量与目标对象之间的联系,从而无依赖地构造出目标对象。目标对象之间存在引用和被引用的关系,利用这一关系,根据对象引用信息构造对象引用链的思路,可生成目标对象的所有引用链。生成引用链的伪代码如下所示:
[0188]
[0189] 从目标对象开始,遍历引用了该目标对象的对象,并判断引用了该对象的对象的类型。在运行时堆模型中,一个对象的类型可能有五种:基础数据类型对象、普通堆对象、类对象、数组对象、引用对象,而其中有可能引用别的对象的只能是普通堆对象、数组对象或类对象。如果当前遍历到的对象不是一个类对象,则继续以此对象为新的目标对象进行下一轮遍历;如果当前遍历到的对象是一个类对象,由于类对象只有静态成员变量能引用其他对象,因此找到该类的某个静态成员变量,能够通过一层层的引用关系,构造出所需的目标对象,此时即寻找到了目标对象的一条引用链。通过不断重复上述的遍历及判断流程,可以找到所有以目标对象结尾、以一个静态成员变量开头的引用链。
[0190] 上述思路能大体上将所有的目标对象引用链找出,但仍存在一些问题。由于运行时堆模型中记录的对象数目庞大,因此整个运行时堆模型中对象之间的引用关系是非常复杂的,不断地遍历引用了对象的新对象,可能经过若干轮次后这一流程仍没法终止,最终导致程序在时间和空间上都消耗过度的资源甚至崩溃。因此,因限制遍历引用关系的深度。构造对象的有效引用链时,一般链长不会特别长,因此限制遍历最深层次为8层,即前述步骤S7B中的“下一轮”最多为第8轮,亦即引用链最长只能包含9个对象,这一限制能有效限制执行的时间与空间。
[0191] 另一方面,对象之间可能存在循环引用。普通的循环引用即两个对象相互引用对方,更广义的循环引用则是若干个对象之间的引用形成了一条引用链,同时链尾元素又引用了链头部元素,形成了一个引用环。即使限定了遍历的最深层次,引用环的存在仍使得引用链寻找方法的额外开销非常大,在环中的遍历步骤都是无效的。为了消除寻找过程中的引用环,执行步骤S7B时,实时记录当前引用链中已经使用的对象,如果遍历过程中遇到了已经使用过的对象,则跳过该对象。
[0192] 解决了对象引用链生成过程中遇到的问题后,能够较快速地正确生成所有最长长度限制以内的对象引用链。对于每一条引用链,其长度越短,其生成代码的可用性可能越高,同时生成代码的难度越小。因此在生成了目标对象的所有引用链后,可将所有引用链按长度从短到长的顺序进行推荐,并生成推荐结果。根据推荐结果选定一条对象引用链,作为之后生成对象构造代码的基本材料,选择时应尽量避免引用链中存在可能会出现构造错误或者构造后不可用的对象,如UI相关类型的对象。
[0193] 对于步骤S8,对于被选择的目标对象引用链,构造代码是从链头的类对象开始的。在网构软件行为反射技术框架1中,构造出的代码最终会运行在应用类加载器环境下,如果需要使用一个类加载器不是应用类加载器的类的相关内容,则需要在构造该类时指定正确的类加载器。运行时堆模型中记录了每个类对象的类加载器,若链头的类对象的类加载器不是应用类加载器,需要构造出该类对象的类加载器。类加载器在堆中也是一个普通对象,其同样可以通过不断遍历引用了对象的新对象的引用链构造得出。构造出类加载器后,可以得到一条完整的引用链,以此为基础进行目标对象构造的代码生成。
[0194] 步骤S9包括:
[0195] 步骤S9A:判断引用链头部的类对象的类加载器是否是应用类加载器,如果是则通过Java反射机制生成类对象,如果不是则递归使用该步骤生成目标类加载器;
[0196] 步骤S9B:在生成好目标类加载器后指定该类加载器并生成类对象;
[0197] 步骤S9C:对于目标对象引用链上的每个对象,通过Java反射机制获取当前引用链上对象的每个域,并判断其是否是下一个对象,如果是则根据该域的名称生成对象构造代码。
[0198] 对于步骤S9,根据之前选择的完整的对象引用链,可以生成对象构造代码。由于目标是不依赖任何多余内容的前提下构造出对象,因此选择使用Java的反射机制来生成代码。使用Java反射机制有两个好处,一是不需要依赖应用的jar包来识别类型和方法调用,二是在构造引用链头部的类对象时,能方便地指定类加载器。对象构造代码生成的伪代码如下所示:
[0199]
[0200]
[0201] 首先判断引用链头部的类对象的类加载器是否是应用类加载器,如果是则通过Java反射机制生成类对象,如果不是则递归使用该步骤生成目标类加载器,在生成好目标类加载器后指定该类加载器并生成类对象。之后对于链上的每个对象,通过Java反射机制获取当前链上对象的每个域,判断其是否是下一个对象,如果是则根据该域的名称生成对象构造代码。
[0202] 使用这一方法生成代码遇到的一个问题是,对象的引用链中存在一些不能直观构造的类。Java对很多类型进行了封装,但运行时堆模型记录的引用关系只能体现出最原始的关系。一个常见的例子是HashMap系列的类。HashMap对象在Java中可以直接通过关键字获取特定的对象或值,但是在运行时堆模型中,其引用关系是这样描述的:HashMap对象的成员变量key仍是对象的关键字引用,但不存在value成员变量,取而代之存在一个名为table的成员变量,其引用了一个数组,该数组即Java在底层为HashMap分配空间时新建的数组,HashMap中的对象根据哈希值存储在数组的对应下标项中;哈希值与之前重复的对象会成为之前对象的next域的一个引用。如果完全按照引用链描述的关系生成代码,按照数组下标的方式获取对象是非常容易出错的,因为当HashMap中存储的对象数目变化时,数组的大小会变,哈希值会变,目标对象并不会固定地存储在数组的某一位置。为了解决这一问题,根据特殊类型的直接使用方法和其在运行时堆模型中的引用关系结构,对常见的Map与Set系列类型做了特殊的代码生成处理,正确生成这些拥有特殊类型的对象的代码。
[0203] 由于通过反射获取不同域对象、调用不同函数的流程是一致的,为了简化生成代码,设计了SmartReflection类基于Java的反射机制对对象进行操作。对于类加载器不是应用类加载器的情况,首先需要额外生成该类加载器的构造代码,同时,在生成链头部类对象的代码时需要多指定两个参数,第二个参数为null,第三个参数为目标类加载器对象。对于需要特殊处理的Map和Set系列对象,则不通过反射来获取,直接对引用链进行特殊处理,并根据关键字直接获取下一个目标对象。
[0204] 通过上述步骤能够得到能正确获取目标数据的完备代码,此时需要将代码整理成接口,从而完成安卓应用的微服务化。由于在使用网构软件行为反射技术框架1监测应用时,为了监测应用的某项功能及运行该功能后所得到的数据,需要在手机上真实地对应用进行操作,如输入文字、点击、选择等等。这使得运行时栈模型中某些函数的参数如字符串、数字等类型的参数具有特殊性,其值依赖于当时对应用的操作。因此,对于最终生成的代码,应检查每个函数调用中的参数,并判断其是否能抽象成为一个输入。提取出所有生成代码中能成为输入的参数后,应将代码封装成函数,并将这些提取出的参数作为函数的输入参数,同时将最后一条函数调用获得的数据作为函数的输出。经过后续的实际测试后,这个函数就是最终的安卓应用某项功能的微服务。
[0205] 基于上述基于对象引用链的对象构造代码生成方法,本发明实施例还提供了一种基于对象引用链的对象构造代码生成系统,如图12所示,该系统包括:目标对象引用链生成模块7、类加载器构造模块8和目标对象构造代码生成模块9;
[0206] 目标对象引用链生成模块7用于根据目标对象间的引用信息生成目标对象的所有引用链;
[0207] 类加载器构造模块8用于判断被选择的目标对象引用链开头的静态对象的类加载器是否与应用类加载器一致,如果不一致,则将类加载器作为新的目标对象返回运行目标对象引用链生成模块7;
[0208] 目标对象构造代码生成模块9用于根据被选择的目标对象引用链生成目标对象构造代码。
[0209] 目标对象引用链生成模块7包括遍历模块、引用链生成子模块;
[0210] 遍历模块用于从目标对象开始,遍历引用了该目标对象的对象,并判断引用了该目标对象的对象的类型,类型包括基础数据类型对象、普通堆对象、类对象、数组对象和引用对象,并在当前遍历到的对象不是一个类对象,则继续以此对象为新的目标对象进行下一轮遍历;这里下一轮最多为第8轮。
[0211] 引用链生成子模块用于在遍历模块当前遍历到的对象是一个类对象时,查找该对象的一个静态成员变量,并根据静态成员变量与目标对象间的引用关系,得到目标对象的一条引用链,并返回运行遍历模块,直到得到所有以目标对象结尾,以静态成员变量开头的引用链。遍历模块在遍历时,实时记录当前引用链中已经使用的对象,如果遍历过程中遇到了已经使用过的对象,则跳过该对象。
[0212] 该基于对象引用链的对象构造代码生成系统还包括引用链推荐模块,引用链推荐模块将所有引用链按长度从短到长的顺序进行推荐,并生成推荐结果。
[0213] 该基于对象引用链的对象构造代码生成系统中的各模块与基于对象引用链的对象构造代码生成方法中的各步骤一一对应,用以执行基于对象引用链的对象构造代码生成方法中的各步骤,各模块的具体工作原理及过程等可参照基于对象引用链的对象构造代码生成方法中的各步骤,在此不再赘述。
[0214] 本发明实施例还提供了一种基于反射的安卓应用微服务化方法,该基于反射的安卓应用微服务化方法包括了上述基于调用栈和依赖路径的函数调用代码生成方法中的步骤S1到步骤S6和上述基于对象引用链的对象构造代码生成方法中的步骤S7到步骤S9,另外还包括下述的步骤S10。具体来说,该基于反射的安卓应用微服务化方法包括如下步骤:
[0215] 步骤S1:在安卓应用运行时,对安卓应用的运行进行监控,得到安卓应用的行为反射运行时模型,然后跳转至步骤S2;行为反射运行时模型包括运行时栈模型和运行时堆模型;
[0216] 步骤S2:标注运行时栈模型中包含目标数据的目标对象,然后跳转至步骤S3;
[0217] 步骤S3:生成目标对象的所有函数调用集,然后跳转至步骤S4;
[0218] 步骤S4:分析使用每一函数调用集生成函数调用代码的难度,并据此为每一函数调用集进行评分,然后跳转到步骤S5;
[0219] 步骤S5:判断被选择的函数调用集是否依赖新对象,当被选择的函数调用集依赖新对象时,跳转至步骤S2,并将依赖的新对象作为目标对象,否则跳转至步骤S6,被选择的函数调用集为根据各函数调用集的评分从所有函数调用集中选择的;
[0220] 步骤S6:将各次选择的函数调用集按序组成函数调用序列,并使用函数调用序列生成可执行的函数调用代码;
[0221] 步骤S7:对于无法在运行时栈模型中生成的目标对象,在运行时堆模型中,根据目标对象间的引用信息生成目标对象的所有引用链;
[0222] 步骤S8:判断被选择的目标对象引用链开头的静态对象的类加载器是否与应用类加载器一致,如果不一致,则将类加载器作为新的目标对象返回执行步骤S7,如果一致则执行步骤S9;
[0223] 步骤S9:根据被选择的目标对象引用链生成目标对象构造代码;
[0224] 步骤S10:将函数调用代码和目标对象构造代码包装成微服务接口。
[0225] 对上述基于调用栈和依赖路径的函数调用代码生成方法中的步骤S1到步骤S6的说明和对上述基于对象引用链的对象构造代码生成方法中的步骤S7到步骤S9的说明也适用于该基于反射的安卓应用微服务化方法中的步骤S1到步骤S9。
[0226] 步骤S4中,分析使用函数调用集生成函数调用代码的难度,并据此为该函数调用集进行评分的步骤包括:
[0227] 统计该函数调用集中函数调用的数目A;
[0228] 统计该函数调用集所依赖的新对象的数目B;
[0229] 统计该函数调用集所依赖的所有新对象的总相关函数调用的数目C;
[0230] 统计该函数调用集中无法在运行时栈模型中构造的新对象数目D;
[0231] 根据数目A、数目B、数目C及数目D各自的预设权重,将数目A、数目B、数目C及数目D进行加权求和,得到该函数调用集的评分。
[0232] 步骤S3中,生成目标对象的所有函数调用集包括如下步骤:
[0233] 查找目标对象从第一次出现到包含目标数据的过程中所有调用的函数以及所有以目标对象为参数的函数;
[0234] 依据运行时栈模型提供的函数调用栈信息,将查找到的函数划分成调用栈层次不完全相同但最后执行逻辑相同的多个函数调用集。
[0235] 步骤S7包括:
[0236] 步骤S7A:从目标对象开始,遍历引用了该目标对象的对象,并判断引用了该目标对象的对象的类型,类型包括基础数据类型对象、普通堆对象、类对象、数组对象和引用对象;
[0237] 步骤S7B:如果当前遍历到的对象不是一个类对象,则继续以此对象为新的目标对象进行下一轮遍历,如果当前遍历到的对象是一个类对象,查找该对象的一个静态成员变量,并根据静态成员变量与目标对象间的引用关系,得到目标对象的一条引用链;
[0238] 步骤S7C:重复步骤S7A和步骤S7B,直到得到所有以目标对象结尾,以静态成员变量开头的引用链。
[0239] 执行步骤S7B时,实时记录当前引用链中已经使用的对象,如果遍历过程中遇到了已经使用过的对象,则跳过该对象。
[0240] 该基于反射的安卓应用微服务化方法中的各步骤与基于调用栈和依赖路径的函数调用代码生成方法和基于对象引用链的对象构造代码生成方法中的相应步骤一致,可参考基于调用栈和依赖路径的函数调用代码生成方法和基于对象引用链的对象构造代码生成方法中的相应步骤的描述,在此不再赘述。
[0241] 根据上述基于反射的安卓应用微服务化方法,本发明实施例还提供了一种基于反射的安卓应用微服务化系统,如图14所示,该系统包括:网构软件行为反射技术框架1、目标对象标注模块2、函数调用集生成模块3、函数调用集评分模块4、判断模块5、函数调用代码生成模块6、目标对象引用链生成模块7、类加载器构造模块8、目标对象构造代码生成模块9和微服务化接口包装模块10。
[0242] 网构软件行为反射技术框架1,用于在安卓应用运行时,对安卓应用的运行进行监控,得到安卓应用的行为反射运行时模型,行为反射运行时模型包括运行时栈模型和运行时堆模型;
[0243] 目标对象标注模块2,用于标注运行时栈模型中包含目标数据的目标对象;
[0244] 函数调用集生成模块3,用于生成目标对象的所有函数调用集;
[0245] 函数调用集评分模块4,用于分析使用每一函数调用集生成函数调用代码的难度,并据此为每一函数调用集进行评分;
[0246] 判断模块5,用于判断被选择的函数调用集是否依赖新对象,当被选择的函数调用集依赖新对象时,返回运行目标对象标注模块2,并将依赖的新对象作为目标对象,否则运行函数调用代码生成模块6,被选择的函数调用集为根据各函数调用集的评分从所有函数调用集中选择的;
[0247] 函数调用代码生成模块6,用于将各次选择的函数调用集按序组成函数调用序列,并使用函数调用序列生成可执行的函数调用代码;
[0248] 目标对象引用链生成模块7,用于根据目标对象间的引用信息生成目标对象的所有引用链;
[0249] 类加载器构造模块8,用于判断被选择的目标对象引用链开头的静态对象的类加载器是否与应用类加载器一致,如果不一致,则将类加载器作为新的目标对象返回运行目标对象引用链生成模块7;
[0250] 目标对象构造代码生成模块9,用于根据被选择的目标对象引用链生成目标对象构造代码;
[0251] 微服务化接口包装模块10,用于将函数调用代码和目标对象构造代码包装成微服务接口。
[0252] 函数调用集评分模块4包括:
[0253] 统计模块,用于统计函数调用集中函数调用的数目A、该函数调用集所依赖的新对象的数目B、该函数调用集所依赖的所有新对象的总相关函数调用的数目C,以及该函数调用集中无法在运行时栈模型中构造的新对象数目D;
[0254] 加权求和模块,用于根据数目A、数目B、数目C及数目D各自的预设权重,将数目A、数目B、数目C及数目D进行加权求和,得到该函数调用集的评分。
[0255] 函数调用集生成模块3包括:
[0256] 函数查找模块,用于查找目标对象从第一次出现到包含目标数据的过程中所有调用的函数以及所有以目标对象为参数的函数;
[0257] 函数划分模块,依据运行时栈模型提供的函数调用栈信息,将查找到的函数划分成调用栈层次不完全相同但最后执行逻辑相同的多个函数调用集。
[0258] 目标对象引用链生成模块7包括遍历模块、引用链生成子模块;
[0259] 遍历模块用于从目标对象开始,遍历引用了该目标对象的对象,并判断引用了该目标对象的对象的类型,类型包括基础数据类型对象、普通堆对象、类对象、数组对象和引用对象,并在当前遍历到的对象不是一个类对象,则继续以此对象为新的目标对象进行下一轮遍历;
[0260] 引用链生成子模块用于在遍历模块当前遍历到的对象是一个类对象时,查找该对象的一个静态成员变量,并根据静态成员变量与目标对象间的引用关系,得到目标对象的一条引用链,并返回运行遍历模块,直到得到所有以目标对象结尾,以所述静态成员变量开头的引用链。
[0261] 遍历模块在遍历时,实时记录当前引用链中已经使用的对象,如果遍历过程中遇到了已经使用过的对象,则跳过该对象。
[0262] 该基于反射的安卓应用微服务化系统中的各模块与上述基于反射的安卓应用微服务化方法中的各步骤一一对应,用以执行上述基于反射的安卓应用微服务化方法中的各步骤,各模块的具体工作原理及过程可参照上述基于反射的安卓应用微服务化方法中的各步骤,在此不再赘述。
[0263] 基于反射的安卓应用微服务化举例:
[0264] 例一:以pp助手应用市场的9.6.0版本的百度地图为例,在百度地图主界面中,点击左上角头像可以看到用户个人界面,继续点击“收藏夹”、“收藏点点”即可看到用户所收藏的地点。本例中需要开发获取用户所收藏地点的微服务。预先在应用中收藏了3个地点用于测试,完成操作后能够看到预先存储的3个地点信息,因此,最终的微服务接口调用后也应产生包含这3个地点信息的数据。
[0265] 为了将上述功能转化成一个微服务,获取用户收藏的地点,使用本发明提供的基于反射的安卓应用微服务化方法来辅助微服务开发。根据该功能的操作流程,首先开启百度地图,打开网构软件行为反射技术框架原型系统,对百度地图进行监控;接着点击头像、收藏夹、收藏点,等待收藏的地点列表出现;最后关闭原型系统,停止监控并导出应用运行时行为模型。此时生成微服务接口所需要的运行时栈模型和运行时堆模型已准备完成。
[0266] 在运行时栈模型中,首先需要标注目标对象。由于最终所需的地点中包含北京大学,以“北京大学”为关键字在运行时栈模型中搜索,获取包含此关键字的所有对象的出现位置。以包含“北京大学”关键字的第一条记录为生成目标,该条函数调用的返回值中包含“北京大学”,此即需要的目标函数。该函数依赖一个新对象,进一步使用本发明的微服务化方法生成该目标对象。
[0267] 例二:以基于pp助手应用市场的6.3.32版本的微信为例。当点击进入一个群聊天室时,用户可以看到已经发出的聊天信息,以及发出聊天信息的用户。本例中需要开发获取某个指定群聊天的消息的微服务。同例一的操作,首先使用网构软件行为反射技术框架原型系统获取该功能的运行时栈模型和运行时堆模型。同时标注目标数据,首先以其中的一条消息“嗯嗯”作为关键字在运行时栈模型中搜索,获取包含此关键字的所有对象的出现位置。仍以第一条函数调用为目标函数,该条函数调用依赖一个新对象0x243b5420,将该对象标注为目标对象,该函数标注为终止点,此时标注流程完成。
[0268] 标注完成后,进行函数调用集推荐。使用本发明提供的基于反射的安卓应用微服务化方法一共产生了15个推荐方案,给出每种方案的四个特征值及最终评分,选择评分最低的函数调用集用于生成代码。评分最低的函数调用集不再依赖新的对象,因此不用进行再一轮的函数调用集生成与选择,此时运行时栈模型部分可以生成代码。此时仍然存在一个在运行时栈模型中无法构造的对象0x22c12040,因此需要进一步在运行时堆模型中构造该对象。将上一步无法构造的对象0x22c12040放入运行时堆模型中搜索,并使用本发明基于反射的安卓应用微服务化方法在运行时堆模型中生成该对象的所有引用链。生成的引用链按长度从短到长显示。比较前5条结果,其类加载器都是应用类加载器,不需要进一步生成类加载器。第5条结果可能使用到Wifi相关内容,第2条和第5条结果其头部的类都是内部类,不适合用于构造对象,因此第1、3、4条都可以用作生成代码,选择第一条引用链,为其生成的代码。
[0269] 将运行时栈模型和运行时堆模型两部分生成的代码结合起来,即可得到最终含有目标关键字“嗯嗯”的字符串。而该字符串不含其他的聊天内容,因此还要设法获取多条聊天内容。使用同样的方法和流程获取含有“20号?15分钟?”关键字的代码,发现前一部分代码完全一致,只有后面多了几行代码,获取包含目标关键字的字符串。通过对代码中重复的模式进行合并,对参数进行抽象,可以看出在数据库相关字符串中,7460729684@chatroom即代表群聊天室的id,14代表了获取聊天记录的条数(因为后面相同的代码模式在运行时栈模型中出现了14次),将这两个值参数化后整理代码,即生成了微信获取群聊天消息的微服务接口。该接口经过测试,能够正确获取指定群聊指定数目的聊天信息。
[0270] 上述实施例仅为优选实施例,并不用以限制本发明的保护范围,在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明的保护范围之内。