CN105824758A - 一种基于执行索引和访问路径的堆区对象比较方法 - Google Patents
一种基于执行索引和访问路径的堆区对象比较方法 Download PDFInfo
- Publication number
- CN105824758A CN105824758A CN201610158676.2A CN201610158676A CN105824758A CN 105824758 A CN105824758 A CN 105824758A CN 201610158676 A CN201610158676 A CN 201610158676A CN 105824758 A CN105824758 A CN 105824758A
- Authority
- CN
- China
- Prior art keywords
- pointer
- snapshot
- coupling
- array element
- access path
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Granted
Links
- 238000000034 method Methods 0.000 title claims abstract description 36
- 230000008878 coupling Effects 0.000 claims description 36
- 238000010168 coupling process Methods 0.000 claims description 36
- 238000005859 coupling reaction Methods 0.000 claims description 36
- 238000013459 approach Methods 0.000 claims description 13
- 230000000052 comparative effect Effects 0.000 claims description 13
- 238000002372 labelling Methods 0.000 claims description 8
- 230000008901 benefit Effects 0.000 abstract description 2
- 238000010835 comparative analysis Methods 0.000 abstract description 2
- 238000005259 measurement Methods 0.000 abstract 1
- 230000008569 process Effects 0.000 description 8
- 238000010586 diagram Methods 0.000 description 5
- 230000000694 effects Effects 0.000 description 2
- 230000013011 mating Effects 0.000 description 2
- 206010008190 Cerebrovascular accident Diseases 0.000 description 1
- 208000006011 Stroke Diseases 0.000 description 1
- 230000008859 change Effects 0.000 description 1
- 230000007547 defect Effects 0.000 description 1
- 238000013461 design Methods 0.000 description 1
- 238000001514 detection method Methods 0.000 description 1
- 238000005516 engineering process Methods 0.000 description 1
- 230000002708 enhancing effect Effects 0.000 description 1
- 230000006870 function Effects 0.000 description 1
- 238000003780 insertion Methods 0.000 description 1
- 230000037431 insertion Effects 0.000 description 1
- 230000003068 static effect Effects 0.000 description 1
- 238000012795 verification Methods 0.000 description 1
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/3604—Software analysis for verifying properties of programs
- G06F11/3612—Software analysis for verifying properties of programs by runtime analysis
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Software Systems (AREA)
- Computer Hardware Design (AREA)
- Quality & Reliability (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Devices For Executing Special Programs (AREA)
- Debugging And Monitoring (AREA)
Abstract
本发明公开了一种基于执行索引和访问路径的堆区对象比较方法,它包含以下步骤:指定一对匹配的程序执行点,以不同的输入执行同一版本程序(或者以同一输入执行不同版本的程序),在匹配的程序执行点捕获相应的堆区快照;赋予每一个快照中每一个对象一个ID;通过ID将不同快照中的对象进行匹配并递归比较匹配的对象;根据匹配结果,生成差异性度量表。本发明与现有的技术相比,其显著优点是:本发明通过结合两种不同的基本匹配算法,克服了访问路径匹配算法中不能有效匹配数组元素的问题,能够更高效、准确的进行对象比较分析。
Description
技术领域
本发明涉及一种基于执行索引和访问路径的堆区对象比较方法,属于程序分析及软件维护等技术领域。
背景技术
现代程序设计语言大多支持面向对象(Object-Oriented)编程范式,例如Java、C++、Python。面向对象的程序在执行过程中会创造许多对象。一般来说,对象被随机的动态分配在堆区中,对象之间通过对象的地址,也就是指针,来进行互相访问。面向对象的程序执行实际上是通过对象之间的交互来完成的。因此,对象分析对面向对象程序的分析十分重要。
对象比较是对象分析的一个重要分支,它主要分为同一次执行不同时间点的对象比较和不同执行间匹配的点之间的比较。一个程序可以接受不同的输入(Input),不同的输入得到不同的执行(Execution)。此外,由于软件在不断的更新,一个程序会有多个版本。所以,同一输入在不同版本的程序上也得到不同的执行。一般来说,我们主要关注不同输入的同版本程序的不同执行和相同输入的不同版本程序的不同执行之间的堆区比较。
本发明主要是解决:相同输入下,不同版本程序的执行过程中创造的对象的比较问题。它可以用来进行调试过程中的缺陷定位以及程序动态更新过程中的对象状态迁移。
一个面向对象程序有若干类(Class)组成,一个类包含了若干域(Field)和方法(Method),每一个域和方法都有一个唯一的ID。一般来说,对象分为实例(Instance)对象和数组(Array)对象。在程序执行过程中,一个对象占有一定长度的内存空间,该内存空间被分割成槽(Slot)。实例对象由类创造,其包含了该类所包含所有的域,也就是说,每一个域对应一个固定的slot,slot通过对应的域来访问其值(Value)。数组对象由一组数组元素的序列组成,每一个数组元素对应一个slot,slot通过一个数值索引(Index)(即该元素存在于序列中的序号)来访问其值。slot的值分为两种:基本数值(例如整型值)和指针。对于基本数值,比较的时候直接比较其数值,对于指针,比较其是否指向匹配的对象。此外,指针还有一个特殊的值,空指针,表明该指针并没有指向任何对象。
程序的执行从一个入口方法开始,执行过程中会调用新的方法。方法是用于匹配的最小执行单元,每一个方法有一个固定的标识符(ID)。不同版本之间的方法可以有相同的ID,但是有不同的代码实现。在一个程序的执行点,我们可以得到一个活动方法的调用序列,从入口方法开始到当前方法。通过这个调用序列,我们可以生成一个CallString。一个CallString是一个由方法ID、该方法当前的指令以及通过该指令调用该方法的次数组成的三元组的序列。除了序列中的最后一个三元组,其余三元组的当前指令必然是一条调用指令。这里,我们用CallString来刻画和匹配程序执行点。在匹配同一版本的不同执行的CallString时,我们只匹配方法ID。在匹配不同版本的不同执行时,除了方法ID,其方法代码也要一致才能匹配。
对象比较一般需要先匹配对象,然后比较匹配对象各个slot值的差异。匹配对象需要首先为每一个对象指派一个标识符(ID),然后将相同ID的对象匹配。最简单的对象ID是对象的地址,但是由于地址分配的随机性,因此该ID不适合不同执行之间的对象比较。另外一种ID是关键域(KeyFields),这种ID能够区分同一个类的不同对象,又能匹配两个集合中的同一个类的对象,但是为了找到能够满足条件的域,对于集合中的每一个对象,算法都需要在另一个集合中遍历,复杂度为O(n2),而且该类中域的语义也不一定满足这种严格的要求,所以这种算法使用范围小,复杂度比较高。还有一种简单的ID是采用计数器,每一个对象按照创建的顺序分配ID。这种ID在局部范围(例如一段顺序执行的代码)有不错的效果,但是在分支较多的程序中,由于不同执行选择的分支执行顺序不同(例如插入执行一段分支),会导致ID差异很大。一种弥补这种程序结构带来的影响办法是通过结构化的执行索引来。
执行索引反映了程序执行的时间点,它将程序执行过程遇到的每条指令的执行给予一个在本次执行中唯一编号,例如上述的计数器就可以实现这样的编号。但是这种索引没有考虑到程序的结构信息和上下文信息,例如CallString。一些已有的高级执行索引考虑到了这些信息,可以提供很好的执行匹配。但是问题是由于不同执行会执行不同的代码,调用不同的方法,因此并不是所有的CallString可以匹配。这个时候,要考虑堆区的拓扑结构来弥补。
堆区中对象可以组织成一个有向图(R,V,E),其中R为一个根指针集合,包含全局变量和当前的局部变量;V为点(对象)的集合,包含堆区中的对象集合;E是边(指针)的集合,包含根指针和对象slot内的指针。每条边都有一个标签,对于根指针则为相应的变量的名称,对于实例对象里的域,则为该域的ID,对于数组元素,则为该元素的索引。在任意的执行时刻点,根指针集合可以唯一确定。对象的访问都是通过指针来进行。从根指针开始,我们可以通过一系列指针,访问到任意的可访问的堆区对象。这个指针序列就是访问路径(AccessPath)。获得访问路径的方式有很多种,一种常见的是就是从根指针开始,生成有向图的深度优先搜索树,那么树中的一条路径(这里边是指针)就是一条访问路径。
访问路径作为对象的ID可以有效匹配对象,但是若路径中存在一个数组元素,则该匹配效果会很差。这是由于不同执行元素插入数组的顺序不同从而导致索引不同,此外,一些元素的索引是不确定的哈希值计算得到。为了弥补这个问题,一个自然而然的解决方式就是结合多种匹配方法,互取长短。因此,本发明提出了一种结合访问路径和执行索引的堆区对象比较方法。
发明内容
由于对象是存在于程序执行过程的内存中的,当我们需要分析对象的时候,需要在一些程序执行点,通过一些工具捕获内存中的对象,存入一个快照当中以便分析。本发明所要解决的技术问题是比较不同堆区快照中的对象,度量不同快照的差异性大小。
本发明的技术方案为:一种基于执行索引和访问路径的堆区对象比较方法,它包含以下步骤:
1)指定一对匹配的程序执行点,以不同的输入执行同一版本程序(或者以同一输入执行不同版本的程序),在匹配的程序执行点捕获相应的堆区快照;
2)赋予每一个快照中每一个对象一个ID;
3)通过ID将不同快照中的对象进行匹配并递归比较匹配的对象;
4)根据匹配结果,生成差异性度量表。
步骤1)的具体步骤包括:
1.1)读取配置文件,指定匹配点的CallString;
1.2)通过代码插桩框架在方法的入口插入构建并检测CallString的代码,同时记录每个对象创建时的CallString;
1.3)执行插桩后的程序;
1.4)若检测到匹配的CallString,则生成堆区快照。
步骤1.2)中构建和检测CallString,记录对象创建的代码执行过程如下:
1.2.1)初始化调用树,从程序的主线程入口开始记录;
1.2.2)在每一个函数的入口,我们都记录下当前方法的ID、调用该方法的指令,以及它的执行次数;
1.2.3)当拦截到新的对象创建时,生成该对象对应执行点的CallString,并记录到该对象中,同时保存到一个全局的哈希表中;
1.2.4)当检测到执行点的CallString与匹配点的CallString相同时,我们就生成当前堆区的快照。
步骤2)中赋予每一个对象一个ID的具体步骤如下:
2.1)初始访问路径为空,根据变量名匹配根指针;
2.2)从匹配的根指针开始,同时深度遍历两个堆区快照,并将访问的指针追加于访问路径之上;
2.3)若通过匹配的指针访问的一对对象类型相同,则匹配该对象,否则不匹配;
2.4)对于匹配的对象,若该对象是实例对象,则直接匹配相同ID域指针;
2.5)若该对象是数组对象,则结合CallString匹配数组元素的指针。
步骤2.5)中匹配数组元素指针的具体步骤如下:
2.5.1)从第一个堆区快照中取出一个不为空的数组元素指针(即该指针指向一个对象);
2.5.2)若第二个堆区快照中存在一个同样不为空的数组元素指针,且这两个指针指向的对象有匹配的CallString,则匹配这两个数组元素指针;
2.5.3)依次执行前两步,不断从第一个堆区快照中取出不为空的数组元素指针,直到该数组对象没有不为空的数组元素指针为止。
步骤3)中比较匹配的对象的具体步骤如下:
3.1)若匹配的对象是实例对象,则比较匹配的域的值,若存在不同值的域,则标记该对象不同;
3.2)若匹配的对象是数组对象,则首先比较其数组元素个数。若数组元素个数不同,则标记该对象不同;
3.3)若数组元素相同,且该数组元素的类型为基本数值,则按照匹配的索引比较对应数组元素的数值;若存在任意不同数值的数组元素,则标记该对象不同;
3.4)若数组元素相同,但该数组元素的类型为指针,若存在任意不匹配的指针,则标记该对象不同。
步骤4)中统计度量信息,生成度量表的步骤包括:
4.1)把匹配的CallString作为时序标志,对齐快照,作为横轴;
4.2)对于每对快照,度量值=相同对象的个数/总的对象个数,作为纵轴;
4.3)生成图表信息。
本发明与现有的技术相比,其显著优点是:
1)高性能:使用CallString记录对象创建时的上下文信息,并借助于哈希表保存了CallString和对象的对应关系,能够快速获得匹配的对象,因此相对于KeyFields算法的复杂度,由原来的O(n2)降为现在的O(n);
2)准确性:扩展了访问路径匹配算法,利用CallString保留的对象创建时的上下文信息,匹配了更多的对象。
附图说明
图1为本发明进行堆区对象比较时的关键步骤示意图。
图2为本发明实施的主要流程图。
具体实施方式
以下结合附图和具体实施例对本发明作进一步详细说明。
本发明通过结合两种不同的基本匹配算法,克服了访问路径匹配算法中不能有效匹配数组元素的问题,能够更高效、准确的进行对象比较分析。
为了实验验证我们的方法,图2给出了具体的实施过程。首先获取两个版本的Java程序代码,进行静态代码插桩,然后运行插桩后的代码并记录快照。这其中使用了两个工具:一个是Java虚拟机工具接口(JVMTI),一个是字节码增强工具(java_crw_demo)。
JVMTI是虚拟机提供的用于监听方法执行、对象生成、线程执行等活动的工具接口,我们开发了一个使用该接口获取方法执行和对象创建信息的Agent,并使用字节码增强工具修改了对象的构造函数。修改后的构造函数能够自动将对象创建时生成的CallString保存到该对象中。为了指定匹配点的CallString,我们首先使用一个jar包比较工具(UPT)来获取类更新信息,并保存到指定的规约文件中。在执行插桩后的程序时,读取该规约文件,把文本中记录的类修改信息记录到运行时用于判别CallString的对象中,当检测到匹配的CallString时,则生成堆区快照。
获得快照以后,我们使用比较工具分别读取每对快照。首先解析该快照,获得对象图,然后匹配对象图的Root集合,并同时遍历两个堆区快照,将访问的指针追加于访问路径之上。根据指针指向的对象类型,我们进行分别处理,获得匹配信息(具体情况,请看发明内容的步骤2)。这里我们使用了OpenJDK开发包中提供的hat接口,用于初步解析获得的快照文件。图1为本发明进行堆区对象比较时的关键步骤示意图。
以上结合附图和具体实施例对本发明的实施方法作了详细的说明,但是本发明不限于上述实施方式,在所属技术领域普通技术人员所具备的知识范围内,还可以在不脱离本发明宗旨的前提下做出各种常规变化,但均在本发明权利要求书的保护范围之内。
Claims (9)
1.一种基于执行索引和访问路径的堆区对象比较方法,其特征在于,它包含以下步骤:
步骤一、指定一对匹配的程序执行点,以同一输入执行不同版本的程序,或者以不同的输入执行同一版本的程序,在匹配的程序执行点捕获相应的堆区快照;
步骤二、赋予每一个快照中每一个对象一个ID;
步骤三、通过ID将不同快照中的对象进行匹配,比较匹配的对象,从而获得每对快照的差异性度量值。
2.根据权利要求1所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于,步骤一中获取堆区快照的步骤包括:
步骤1.1指定匹配点的CallString;
步骤1.2通过代码插桩框架在方法的入口插入构建并检测CallString的代码,同时记录每个对象创建时的CallString;
步骤1.3执行插桩后的程序,若检测到匹配的CallString,则生成堆区快照。
3.根据权利要求2所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于,步骤1.2中构建和检测CallString,记录对象创建的代码执行过程如下:
步骤1.2.1初始化调用树,从程序的主线程入口开始记录;
步骤1.2.2在每一个函数的入口,都记录下当前方法的ID、调用该方法的指令,以及它的执行次数;
步骤1.2.3当拦截到新的对象创建时,生成该对象对应执行点的CallString,并记录到该对象中,同时保存到一个全局的哈希表中;
步骤1.2.4当检测到执行点的CallString与匹配点的CallString相同时,就生成当前堆区的快照。
4.根据权利要求1所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于,步骤二中赋予每一个对象一个ID的具体步骤包括:
步骤2.1初始访问路径为空,根据变量名匹配根指针;
步骤2.2从匹配的根指针开始,同时深度遍历两个堆区快照,并将访问的指针追加于访问路径之上;
步骤2.3若通过匹配的指针访问的一对对象类型相同,则匹配该对象,否则不匹配;
步骤2.4对于匹配的对象,若该对象是数组对象,则结合CallString匹配数组元素的指针。
5.根据权利要求4所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于:步骤2.4中对于匹配的对象,若该对象是实例对象,则直接匹配相同ID域指针。
6.根据权利要求5所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于:步骤2.4中对于匹配的数组对象,从一个堆区快照中依次获取该对象不为空的元素指针,与另一个堆区快照中的数组对象的元素指针进行匹配,若这个两个指针指向的对象有相同的CallString,则匹配这两个数组元素指针。
7.根据权利要求5所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于,步骤2.4中匹配数组元素指针的具体步骤如下:
步骤2.4.1从第一个堆区快照中取出一个不为空的数组元素指针,即该指针指向一个对象;
步骤2.4.2若第二个堆区快照中存在一个同样不为空的数组元素指针,且这两个指针指向的对象有匹配的CallString,则匹配这两个数组元素指针;
步骤2.4.3依次执行前两步,不断从第一个堆区快照中取出不为空的数组元素指针,直到该数组对象没有不为空的数组元素指针为止。
8.根据权利要求5所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于,步骤三中比较匹配的对象的具体步骤如下:
步骤3.1若匹配的对象是实例对象,则比较匹配的域的值,若存在不同值的域,则标记该对象不同;
步骤3.2若匹配的对象是数组对象,则首先比较其数组元素个数;若数组元素个数不同,则标记该对象不同;
步骤3.3若数组元素相同,且该数组元素的类型为基本数值,则按照匹配的索引比较对应数组元素的数值;若存在任意不同数值的数组元素,则标记该对象不同;
步骤3.4若数组元素相同,但该数组元素的类型为指针,若存在任意不匹配的指针,则标记该对象不同。
9.根据权利要求8所述的基于执行索引和访问路径的堆区对象比较方法,其特征在于,步骤三中统计度量信息,生成度量表的步骤包括:
步骤3.5把匹配的CallString作为时序标志,对齐快照,作为横轴;
步骤3.6对于每对快照,度量值=相同对象的个数/总的对象个数,作为纵轴;
步骤3.7生成图表信息。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201610158676.2A CN105824758B (zh) | 2016-03-21 | 2016-03-21 | 一种基于执行索引和访问路径的堆区对象比较方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201610158676.2A CN105824758B (zh) | 2016-03-21 | 2016-03-21 | 一种基于执行索引和访问路径的堆区对象比较方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN105824758A true CN105824758A (zh) | 2016-08-03 |
CN105824758B CN105824758B (zh) | 2018-09-21 |
Family
ID=56525216
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201610158676.2A Active CN105824758B (zh) | 2016-03-21 | 2016-03-21 | 一种基于执行索引和访问路径的堆区对象比较方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN105824758B (zh) |
Cited By (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN108762749A (zh) * | 2018-05-24 | 2018-11-06 | 福州大学 | 基于代码分析的系统对象图自动生成方法 |
CN109635228A (zh) * | 2018-12-07 | 2019-04-16 | 北京锐安科技有限公司 | 有序数组间差异度的确定方法、装置、设备及存储介质 |
-
2016
- 2016-03-21 CN CN201610158676.2A patent/CN105824758B/zh active Active
Non-Patent Citations (3)
Title |
---|
MARK MARRON ETC.: "Abstracting Runtime Heaps for Program Understanding", 《IEEE TRANSACTIONS ON SOFTWARE ENGINEERING 》 * |
STEPHEN MAGILL ETC.: "Automating Object Transformations for Dynamic Software Updating", 《OOPSLA "12 PROCEEDINGS OF THE ACM INTERNATIONAL CONFERENCE ON OBJECT ORIENTED PROGRAMMING SYSTEMS LANGUAGES AND APPLICATIONS》 * |
TIANXIAO GU ETC.: "Low-disruptive Dynamic Updating of Java Applications", 《INFORMATION AND SOFTWARE TECHNOLOGY》 * |
Cited By (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN108762749A (zh) * | 2018-05-24 | 2018-11-06 | 福州大学 | 基于代码分析的系统对象图自动生成方法 |
CN109635228A (zh) * | 2018-12-07 | 2019-04-16 | 北京锐安科技有限公司 | 有序数组间差异度的确定方法、装置、设备及存储介质 |
Also Published As
Publication number | Publication date |
---|---|
CN105824758B (zh) | 2018-09-21 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN102073589B (zh) | 一种基于代码静态分析的数据竞争检测方法及系统 | |
CN106502745B (zh) | 一种函数调用方法和装置 | |
CN102073588B (zh) | 一种基于代码静态分析的多线程死锁检测方法及系统 | |
CN106557413A (zh) | 基于代码覆盖率获取测试用例的方法和设备 | |
CN110007957A (zh) | 调用链路构建方法、装置及设备 | |
Haller et al. | Mempick: High-level data structure detection in c/c++ binaries | |
CN107193732B (zh) | 一种基于路径比对的校验函数定位方法 | |
CN104346384A (zh) | 一种小文件处理方法及装置 | |
CN112380120B (zh) | 单元测试代码结构自动解析与路径分析方法 | |
CN105808438A (zh) | 一种基于函数调用路径的测试用例复用方法 | |
CN111723087A (zh) | 数据血缘关系的挖掘方法、装置、存储介质和电子设备 | |
CN114389978B (zh) | 一种基于静态污点分析的网络协议侧信道检测方法和系统 | |
CN101458630B (zh) | 一种基于硬件模拟器的自修改代码识别方法 | |
CN105824758A (zh) | 一种基于执行索引和访问路径的堆区对象比较方法 | |
CN106407233A (zh) | 一种数据处理方法和设备 | |
CN112579440B (zh) | 一种虚拟测试依赖对象的确定方法及装置 | |
Caballero et al. | ARTISTE: Automatic generation of hybrid data structure signatures from binary code executions | |
CN116933267A (zh) | 一种符号执行的智能合约漏洞检测方法、系统和设备 | |
Singh et al. | MG++: Memory graphs for analyzing dynamic data structures | |
CN114676061A (zh) | 一种基于知识图谱自动化固件检测方法 | |
CN102981919B (zh) | 快速定位错误源头的内存管理方法 | |
CN106528179A (zh) | 一种Java类依赖关系的静态识别方法 | |
CN105204997A (zh) | 软件缺陷检测方法及装置 | |
Pettersson et al. | Efficient and accurate software pattern detection | |
CN107015909B (zh) | 基于代码变更分析的测试方法及装置 |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
C06 | Publication | ||
PB01 | Publication | ||
C10 | Entry into substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant | ||
TR01 | Transfer of patent right | ||
TR01 | Transfer of patent right |
Effective date of registration: 20200623 Address after: No. 41-1, Qianfo Shandong Road, Lixia District, Jinan City, Shandong Province Patentee after: SHANDONG CIVIC SE COMMERCIAL MIDDLEWARE Co.,Ltd. Address before: No. 163 Qixia Xianlin Avenue District of Nanjing City, Jiangsu province 210046 Patentee before: NANJING University |