一种利用Proxy对象进行web应用内存泄漏检测的方法
未命名
09-22
阅读:105
评论:0
一种利用proxy对象进行web应用内存泄漏检测的方法
技术领域
1.本发明涉及内存泄漏检测技术领域,更确切地说,它涉及一种利用proxy对象进行web应用内存泄漏检测的方法。
背景技术:
2.web应用程序现在已经越来越广泛地被使用,但是web应用引起的内存泄漏,一直是引起web应用系统性能下降的主要原因。web浏览器本身需占用大量用户内存,web应用内存泄露又会进一步增加内存消耗。当内存消耗达到一定程度时,浏览器将加快内存回收的频率以改善运行环境,但这又导致浏览器及web应用程序变慢,表现为程序变得卡顿。不仅如此,web应用程序还可能存在着因各种各样原因无法被浏览器回收的内存,随着无法回收的内存越积越多,web应用程序甚至是浏览器本身将会因内存耗尽而崩溃。因而解决内存泄露问题是提高web应用程序稳定性的重要的一环。
3.国内外内存检测算法主要有静态分析和动态分析两种。
4.静态分析是从源代码级分析泄露的成因,或者通过将程序堆中的对象图生成支配树,通过对支配树的分析找出泄露源,或者预先设定几种常见的javascript内存泄露模式,通过模式匹配找到内存泄露的成因,静态方法在适应性上较差,准确性和检出率较低。
5.动态分析是驱动程序运行,在运行中分析web应用内存前后的差值从而得到内存泄露的原因。现在普遍且有效的方法是:基于在现代网站中用户会经常反复回到相似视觉状态(如邮箱程序会经常回到邮箱的主界面)且用户两次访问相似的视觉状态会消耗大致相同的内存这一基本事实,将两次访问间的持续增长作为内存泄露指示器。但其仍无法避免需要编写驱动视觉状态的用例脚本,并且由于动态分析的算法的缺陷,需要多次驱动页面回到同一个视觉状态,但是从回到原始页面到检测分析,耗时过长。仅针对的一个页面(不含各种交互)的内存泄露检测就可能会长达5分钟,这对于一些多页应用来说是难以接受的。另一些改进方法,如基于脚本预测和重组的内存泄露测试加速技术,试图通过基于机器学习方法和脚本重组优化方法,预测得到更可能造成内存泄漏的功能测试脚本,检测到泄露点。但由于机器学习方法需要大量的用例数据集,应用的广泛性和训练后的实际准确率比较受限。
6.总体来说,动态分析受制于用例,只能在用例覆盖的代码检测出泄露。而静态分析不受制于用例,但其对于javascript这类动态语言不合适,其运行时间通常很长并且准确性不高。
技术实现要素:
7.本发明的目的是针对现有技术的不足,提出了一种利用proxy对象进行web应用内存泄漏检测的方法。
8.第一方面,提供了一种利用proxy对象进行web应用内存泄漏检测的方法,包括:
9.s1、启动网络代理;
10.s2、根据用户配置启动浏览器;
11.s3、截获浏览器的请求,网络代理会将目标网页的javascript代码进行转译,返回浏览器;
12.s4、运行泄漏检测算法以找出泄漏点。
13.作为优选,s4包括:
14.s401、代码注入:注入全局辅助函数与全局变量;
15.s402、代码转译:对作用域进行转换,将作用域的转换成直接的对象形式,并将其维护在一个对象树上,这棵对象树的根节点即是全局作用域;
16.s403、对象增长标记:在每次状态迭代结束后从全局作用域出发遍历所有被代理对象,找到属性增长较快的对象,从而确认泄露点;
17.s404、堆栈跟踪生成:在运行额外循环时,网络代理根据泄露对象匹配当前赋值路径,如果匹配成功则捕获当前堆栈信息;
18.s405、输出:读取堆栈跟踪信息通过转译时生成文件源映射,找到原始代码行列,读取对应的评分信息,进行泄漏类型推断,输出最终结果。
19.作为优选,s401中,所述全局辅助函数用于新建对象代理、创建函数作用域、遍历全部对象、标记全局对象属性数、计算泄漏对象的属性条目的平均增长趋势和生成泄露报告函数;全局变量包括全局作用域对象、泄露信息对象和全局作用域原始属性对象。
20.作为优选,s4还包括:
21.泄露评价:遍历全局对象树,对那些被标记为增长对象的属性条目数量历史列表进行求值,从而获取属性条目平均增长趋势,并进行排名从而区分泄漏的重要程度。
22.作为优选,s4还包括:
23.泄露分析:从作用域的类别入手,在对象树的生成和维护过程中,每个对象的类型会被标记;如果全局对象发生泄漏则认为是全局缓存泄漏,如果函数内对象发生泄漏则认为是闭包泄漏。
24.作为优选,s2中,利用输入脚本驱动web页面进行状态转换;所述输入脚本构建了状态转换列表,状态转换列表由两部分组成:检查函数和控制语句,前者检查当前状态是否就绪,后者驱动页面进入循环列表的下一个状态;通过驱动状态转换列表,根据输入脚本提供的其它辅助参数多次驱动页面回到同一个页面状态。
25.作为优选,s401中,建立一个文件源映射,记录程序在代码注入前后的内存对应关系。
26.作为优选,s405中,输出的最终结果包含泄漏对象在对象树上的访问路径、泄漏的堆栈跟踪信息、泄漏类型信息、泄漏评分和泄漏相关源代码。
27.第二方面,提供了一种利用proxy对象进行web应用内存泄漏检测的装置,用于执行第一方面任一所述的利用proxy对象进行web应用内存泄漏检测的方法,包括:
28.第一启动模块,用于启动网络代理;
29.第二启动模块,用于根据用户配置启动浏览器;
30.截获模块,用于截获浏览器的请求,网络代理会将目标网页的javascript代码进行转译,返回浏览器;
31.检测模块,用于运行泄漏检测算法以找出泄漏点。
32.第三方面,提供了一种计算机存储介质,所述计算机存储介质内存储有计算机程序;所述计算机程序在计算机上运行时,使得计算机执行第一方面任一所述的利用proxy对象进行web应用内存泄漏检测的方法。
33.本发明的有益效果是:
34.1.本发明不是对运行中的内存堆分析,找到内存泄露点,而是对对象树进行分析,找到属性增长较快的对象,从而确认泄露点,极大地降低了内存堆分析开销,节省了时间,克服了常用动态分析方法耗时长的缺陷。以普通一页web页面(不含各种交互)为例,对对象树的分析在秒级单位就能完成。
35.2.本发明不是基于用例的方法,不需要设计特定的用例,更不需要用诸如机器学习算法去改进用例。
36.3.本发明对原始web应用程序影响小,应用程序可以实现实时检测或者自动巡检。
附图说明
37.图1为一种利用proxy对象进行web应用内存泄漏检测的方法的总体架构图;
38.图2为输入脚本及任务配置类型定义示意图;
39.图3为转译前代码示意图;
40.图4为转译后代码示意图;
41.图5为输出结果示意图。
具体实施方式
42.下面结合实施例对本发明做进一步描述。下述实施例的说明只是用于帮助理解本发明。应当指出,对于本技术领域的普通人员来说,在不脱离本发明原理的前提下,还可以对本发明进行若干修饰,这些改进和修饰也落入本发明权利要求的保护范围内。
43.实施例1:
44.针对web应用程序语言javascript这类动态类型语言,通过运行时的程序内存占用情况分析,找出内存泄露的原因和在程序段中的位置。分析过程中,要使得分析工作对应用本身的运行干扰最小。尽量不使用或少使用依赖测试用例的动态测试方法。
45.对此,本技术实施例提供了一种利用proxy对象进行web应用内存泄漏检测的方法,该方法是基于javascript语言本身的一种动态分析方法,不需要其他的编程语言工具和运行环境,其基本思想是对javascript的所有对象进行监控并不断驱动web应用回到同一个状态,找出那些属性条目不断增长的对象,就可认为是发生内存泄漏的对象。
46.对于web应用来说,内存泄漏可以认为是页面回到类似的视觉状态的而未能释放掉的内存。比如在购物网站,往空购物车添加一个商品,然后清空,多次重复,回到清空状态,之前往购物车添加的商品数据就应该被清空,如果那个代表购物车的数据结构的属性条数持续增长,那么这个数据结构则可认为是发生内存泄漏。javascript在es2016标准中提供了一个名为proxy的对象,proxy可以对对象进行代理,拦截所有对对象的赋值操作。因而可以利用proxy的这一特性,通过设置赋值拦截函数获取本次赋值的堆栈跟踪信息,确定赋值的源头
47.如图1所示,本技术实施例提供的利用proxy对象进行web应用内存泄漏检测的方
法包括:
48.s1、启动网络代理。
49.具体的,启动一个名为anyproxy网络代理库代理chrome实例的网络流量。
50.s2、根据用户配置启动浏览器。
51.s2中,利用输入脚本驱动web页面进行状态转换;所述输入脚本构建了状态转换列表,状态转换列表由两部分组成:检查函数和控制语句,前者检查当前状态是否就绪,后者驱动页面进入循环列表的下一个状态;通过驱动状态转换列表,根据输入脚本提供的其它辅助参数多次驱动页面回到同一个页面状态。
52.如图2所示,输入脚本是用户提供的用以驱动web页面状态转换的脚本。包含了需要查找内存泄漏的初始链接地址、页面循环列表、页面循环迭代次数、打开页面的超时时间、查看页面是否就绪的检查函数调用周期和对需要登录的页面的登录辅助函数。本技术实施例通过驱动这个列表,根据输入脚本提供的其它辅助参数多次驱动页面回到同一个页面状态。
53.具体的,本技术实施例选择了chrome-debugging-client这个库。这个库从本地chrome默认安装路径上启动一个chrome实例,并支持各种chrome启动的初始化参数。通过这个库本方法在运行时启动chrome实例,并通过devtools-protocol协议控制chrome开启目标页面执行相应操作。
54.s3、截获浏览器的请求,网络代理会将目标网页的javascript代码进行转译,返回浏览器。
55.s4、运行泄漏检测算法以找出泄漏点。
56.s4包括:
57.s401、代码注入:注入全局辅助函数与全局变量;所述全局辅助函数用于新建对象代理、创建函数作用域、遍历全部对象、标记全局对象属性数、计算泄漏对象的属性条目的平均增长趋势和生成泄露报告函数;全局变量包括全局作用域对象、泄露信息对象和全局作用域原始属性对象。注入的全局辅助函数与对象兼具与转译后代码交互和与浏览器驱动程序交互的功能。浏览器驱动程序通过运行辅助函数既可以完成预定操作。
58.具体的,在接收到html类型的请求时,往html head标签最顶部插入一个script标签,script标签的内容为本方法全局的辅助函数和变量。同时本方法检查html上其它非链接类型的script标签,获取其内容进行作用域转换,代码注入和转译完成后返回数据给浏览器。在接收到javascript类型的请求时,本方法转译代码后返回。
59.此外,由于内存泄露的原因在于很多变量在本地作用域被清空,但是它的作用域实际是全局作用域,因而属性变量实际并没有清除。因此必须沿着从本地作用域到全局作用域的路径查找这些变量,并加以处理。相同地,javascript中的原型链是函数查找的路径。作用域和原型链都被转化为了proxy对象,当网络代理拦截到页面时,就将这些新的对象注入到原有页面上。由于代码注入改变了源程序,也改变了源程序内存占用情况,所以要建立一个文件源映射(sourcemap),记录程序在代码注入前后的内存对应关系。
60.s402、代码转译:对作用域进行转换,将作用域的转换成直接的对象形式,并将其维护在一个对象树上,这棵对象树的根节点即是全局作用域。
61.需要说的是,本技术实施例通过浏览器驱动模块进入输入脚本定义的页面相应状
态。在第一次进入页面时,本技术实施例会将页面的所有对象(包括各个作用域也会被转化成一个实际对象)自顶向下构建成一个对象树,页面所有的对象访问和设置都会被代理到这棵树上。
62.图3、图4分别展示了转译前和转译后的代码。在图4中,$$$scope$$$是作用域的对象形式,第一个$$$scope$$$是全局作用域。在代码注入时就已经创建完成。在函数内,每一个函数第一行代码都会被注入这个如图4所示的$$$createfunctionscope$$$函数创建作用域代理。所有作用域内的属性声明和引用都会被转换到代理作用域对象。
63.为了模拟作用域变量向上查找的特性,嵌套作用域的内部作用域的代理对象的原型会被指向到上级作用域代理对象。这种方式实现使得属性访问代理变得十分自然,不需要额外的代码。但在向属性赋值时,代理必须手动实现向上查找,不然会造成本对外部作用域的赋值赋在内部作用域。因此本方法在创建作用域时生成自身的属性映射表(属性-》作用域代理对象的映射),并在赋值时维护。在子作用域创建时,子作用域拉取父作用域的属性映射表并维护属性映射表,自身创建一个新的映射表,原型引用父映射表,这样方法就实现了赋值时快速作用域查找。
64.s403、对象增长标记:对象属性数量标记在每次状态迭代结束后从全局作用域出发遍历所有被代理对象,通过object.getownpropertynames()获取对象的属性名称列表,然后在过滤以$$$开头结尾的算法内建辅助属性之后或属性条数并赋值到对象的$$$propertynumber$$$数组里,在最后一轮附加的运行中,本技术实施例通过检查$$$propertynumber$$$的值数量变化情况,将持续增长的路径标记到全局的$$$leaks$$$对象。
65.s404、堆栈跟踪生成:在运行额外循环时,网络代理根据$$$leaks$$$匹配当前赋值路径,如果匹配成功则用error.capturestacktrace api捕获当前堆栈信息,更新进$$$leaks$$$。如果泄露值相同,那么就过滤这一次的堆栈跟踪不赋值。
66.s405、输出:读取堆栈跟踪信息通过转译时生成文件源映射,找到原始代码行列,读取对应的评分信息,进行泄漏类型推断,输出最终结果。输出包含泄漏对象在对象树上的访问路径、泄漏的堆栈跟踪信息、泄漏类型信息、泄漏评分和泄漏相关源代码。
67.具体的,本技术实施例读取堆栈跟踪信息通过转译时生成sourcemap找到原始代码行列,读取对应的评分信息,进行泄漏类型推断,输出最终结果。图5展示了图2经过上述流程后的输出结果,其包含四项信息dummypath,propertynumber,growthrate,stacktraces和type。dummypath是泄露对象的大致定位信息,用于区分泄露源。propertynumber是每一轮运行检查到的泄露对象属性数目,stacktraces是泄露对象的值分配跟踪信息,growthrate是属性的平均增长率,单位是%,type是泄露的类型。
68.实施例2:
69.在实施例1的基础上,本技术实施例提供了另一种利用proxy对象进行web应用内存泄漏检测的方法,包括:
70.s1、启动网络代理;
71.s2、根据用户配置启动浏览器;
72.s3、截获浏览器的请求,网络代理会将目标网页的javascript代码进行转译,返回浏览器;
73.s4、运行泄漏检测算法以找出泄漏点。
74.s4包括:
75.s401、代码注入:注入全局辅助函数与全局变量;
76.s402、代码转译:对作用域进行转换,将作用域的转换成直接的对象形式,并将其维护在一个对象树上,这棵对象树的根节点即是全局作用域;
77.s403、对象增长标记:在每次状态迭代结束后从全局作用域出发遍历所有被代理对象,找到属性增长较快的对象,从而确认泄露点;
78.s404、堆栈跟踪生成:在运行额外循环时,网络代理根据泄露对象匹配当前赋值路径,如果匹配成功则捕获当前堆栈信息;
79.s405、输出:读取堆栈跟踪信息通过转译时生成文件源映射,找到原始代码行列,读取对应的评分信息,进行泄漏类型推断,输出最终结果。
80.此外,s4还包括:
81.泄露评价:泄漏评价是对查找出来的泄漏进行排名从而区分泄漏的重要程度。一般来说内存泄漏的评价手段是泄漏量,需要对不同状态的堆使用情况进行分析,这无疑是一个巨大的开销。本方法采用了属性条目平均增长趋势。来评价泄露程度。评价算法通过遍历全局对象树,对那些被标记为增长对象的属性条目数量历史列表进行求值,从而获取属性条目平均增长趋势。
82.进一步地,s4还包括:
83.泄露分析:泄漏分析从作用域的类别入手,在对象树的生成和维护过程中,每个对象的类型会被标记。全局作用域被标记为global,函数作用域被标记为closure,对象会被标记为object。如果全局对象发生泄漏可认为是全局缓存泄漏,如果函数内对象发生泄漏可认为是闭包泄漏。对于一些更细节的泄漏类型,本技术实施例不做分析。因而本技术实施例对泄漏类型进行粗略的标记。
84.需要说明的,本实施例中与实施例1相同或相似的部分可相互参考,在本技术中不再赘述。
85.实施例3:
86.在实施例1的基础上,本技术实施例3提供了一种利用proxy对象进行web应用内存泄漏检测的装置,包括:
87.第一启动模块,用于启动网络代理;
88.第二启动模块,用于根据用户配置启动浏览器;
89.截获模块,用于截获浏览器的请求,网络代理会将目标网页的javascript代码进行转译,返回浏览器;
90.检测模块,用于运行泄漏检测算法以找出泄漏点。
91.具体的,本实施例所提供的装置为实施例1提供的方法对应的装置,因此,在本实施例中与实施例1相同或相似的部分,可相互参考,在本技术中不再赘述。
92.综上所述,本发明提出了一种利用proxy对象进行web应用内存泄漏检测的方法。通过对javascript代码进行转译将所有的变量访问转移到代理proxy对象上,能够对目标对象的操作进行拦截,实现对赋值的实时监测与调用栈分析,从而精确定位泄漏点。因为完全借用javascript本身能力实现,因而本方法有很强的自适应能力,对不同对象的代理只
需要实现同一个逻辑即可,易于算法后续的优化改进。
技术特征:
1.一种利用proxy对象进行web应用内存泄漏检测的方法,其特征在于,包括:s1、启动网络代理;s2、根据用户配置启动浏览器;s3、截获浏览器的请求,网络代理会将目标网页的javascript代码进行转译,返回浏览器;s4、运行泄漏检测算法以找出泄漏点。2.根据权利要求1所述的利用proxy对象进行web应用内存泄漏检测的方法,其特征在于,s4包括:s401、代码注入:注入全局辅助函数与全局变量;s402、代码转译:对作用域进行转换,将作用域的转换成直接的对象形式,并将其维护在一个对象树上,这棵对象树的根节点即是全局作用域;s403、对象增长标记:在每次状态迭代结束后从全局作用域出发遍历所有被代理对象,找到属性增长较快的对象,从而确认泄露点;s404、堆栈跟踪生成:在运行额外循环时,网络代理根据泄露对象匹配当前赋值路径,如果匹配成功则捕获当前堆栈信息;s405、输出:读取堆栈跟踪信息通过转译时生成文件源映射,找到原始代码行列,读取对应的评分信息,进行泄漏类型推断,输出最终结果。3.根据权利要求2所述的利用proxy对象进行web应用内存泄漏检测的方法,其特征在于,s401中,所述全局辅助函数用于新建对象代理、创建函数作用域、遍历全部对象、标记全局对象属性数、计算泄漏对象的属性条目的平均增长趋势和生成泄露报告函数;全局变量包括全局作用域对象、泄露信息对象和全局作用域原始属性对象。4.根据权利要求3所述的利用proxy对象进行web应用内存泄漏检测的方法,其特征在于,s4还包括:泄露评价:遍历全局对象树,对那些被标记为增长对象的属性条目数量历史列表进行求值,从而获取属性条目平均增长趋势,并进行排名从而区分泄漏的重要程度。5.根据权利要求4所述的利用proxy对象进行web应用内存泄漏检测的方法,其特征在于,s4还包括:泄露分析:从作用域的类别入手,在对象树的生成和维护过程中,每个对象的类型会被标记;如果全局对象发生泄漏则认为是全局缓存泄漏,如果函数内对象发生泄漏则认为是闭包泄漏。6.根据权利要求5所述的利用proxy对象进行web应用内存泄漏检测的方法,其特征在于,s2中,利用输入脚本驱动web页面进行状态转换;所述输入脚本构建了状态转换列表,状态转换列表由两部分组成:检查函数和控制语句,前者检查当前状态是否就绪,后者驱动页面进入循环列表的下一个状态;通过驱动状态转换列表,根据输入脚本提供的其它辅助参数多次驱动页面回到同一个页面状态。7.根据权利要求6所述的利用proxy对象进行web应用内存泄漏检测的方法,其特征在于,s401中,建立一个文件源映射,记录程序在代码注入前后的内存对应关系。8.根据权利要求7所述的利用proxy对象进行web应用内存泄漏检测的方法,其特征在于,s405中,输出的最终结果包含泄漏对象在对象树上的访问路径、泄漏的堆栈跟踪信息、
泄漏类型信息、泄漏评分和泄漏相关源代码。9.一种利用proxy对象进行web应用内存泄漏检测的装置,其特征在于,用于执行权利要求1至8任一所述的利用proxy对象进行web应用内存泄漏检测的方法,包括:第一启动模块,用于启动网络代理;第二启动模块,用于根据用户配置启动浏览器;截获模块,用于截获浏览器的请求,网络代理会将目标网页的javascript代码进行转译,返回浏览器;检测模块,用于运行泄漏检测算法以找出泄漏点。10.一种计算机存储介质,其特征在于,所述计算机存储介质内存储有计算机程序;所述计算机程序在计算机上运行时,使得计算机执行权利要求1至8任一所述的利用proxy对象进行web应用内存泄漏检测的方法。
技术总结
本发明涉及一种利用Proxy对象进行web应用内存泄漏检测的方法,包括启动网络代理;根据用户配置启动浏览器;截获浏览器的请求,网络代理会将目标网页的JavaScript代码进行转译,返回浏览器;运行泄漏检测算法以找出泄漏点。本发明的有益效果是:本发明不是对运行中的内存堆分析,找到内存泄露点,而是对对象树进行分析,找到属性增长较快的对象,从而确认泄露点,极大地降低了内存堆分析开销,节省了时间,克服了常用动态分析方法耗时长的缺陷。以普通一页web页面为例,对对象树的分析在秒级单位就能完成。级单位就能完成。级单位就能完成。
技术研发人员:李飞 杨海波 郭鸣 丁雷鸣
受保护的技术使用者:浙大城市学院
技术研发日:2023.06.26
技术公布日:2023/9/20
版权声明
本文仅代表作者观点,不代表航家之家立场。
本文系作者授权航家号发表,未经原创作者书面授权,任何单位或个人不得引用、复制、转载、摘编、链接或以其他任何方式复制发表。任何单位或个人在获得书面授权使用航空之家内容时,须注明作者及来源 “航空之家”。如非法使用航空之家的部分或全部内容的,航空之家将依法追究其法律责任。(航空之家官方QQ:2926969996)
航空之家 https://www.aerohome.com.cn/
航空商城 https://mall.aerohome.com.cn/
航空资讯 https://news.aerohome.com.cn/