本发明专利涉及安卓软件应用,内存泄露检测领域,尤其涉及一种基于安卓应用多入口特性的activity泄露检测方法。
背景技术:
近年来,随着移动设备的普及,基于移动设备的安卓应用数量不断增加。然而,由于安卓复杂的生命周期管理机制,开发安卓应用极容易引入泄露activity等构件的可能性。这些潜在的应用构件的泄露,会不断消耗系统内存等资源,导致应用卡顿甚至崩溃,极大的影响用户体验和商家品牌形象。为此,如何自动化高效的检测应用潜在的activity构件的泄露,有着极大的意义。然而,现有检测安卓应用activity泄露的工作要么需要大量的人工介入,要么难以重现泄露场景。为此,本发明旨在利用安卓应用多入口特性来快速检测安卓应用潜在的activity构件的泄露现象。
技术实现要素:
本发明主要针对现有工作的不足,提出了一种基于安卓应用多入口特性来快速检测安卓应用潜在的activity构件泄露的方法。
该方法基于以下现实:安卓应用是多入口的,每个activity都可独立的被启动;当“开发者选项”中“不保留活动”选项被选中,则应用在运行过程中所有不可见的activity会被立即自动销毁;activity构件都提供了一系列刻画其状态的域(field),通过对这些域(field)值的比较,可以判断实例是否已被销毁;不能被gc回收的对象实例,一定存在通往gcroot的不包含softreference、weakreference、phantomreference、finalizerreference以及finalizer类型对象的路径。
为了实现上述发明目的,本发明采用的技术方案为:
一、本发明的一种基于安卓应用多入口特性的activity构件泄露检测方法,主要过程包括:
a)在测试机(安卓实体机或虚拟机)的“开发者选项”中打开“不保留活动”,使得一旦离开一个activity则立刻自动销毁该activity;
b)安装待检测应用;
c)逐个启动并销毁待测试安卓应用所包含的所有activity;
d)获取应用堆栈内存信息;
e)分析获取得到的应用堆栈内存,检测泄露的应用构件。
二、本方案首先要求能够自动的启动并销毁待测试安卓应用所包含的所有activity,这一过程主要包括以下步骤:
a)利用逆向工程工具apktool对待检测安卓应用.apk文件进行反编译,获取应用安卓menifest.xml描述文件,并通过分析安卓menifest.xml文件来进一步获取应用所包含的所有activity的列表,记为lactivity;
b)逐个启动lactivity中的每一个activity。此处,主要是利用安卓自带的“amstart”指令逐个启动待检测应用的所有activity。需注意的是,“amstart”命令需带参数“–activity-clear-task”,以确保每个task栈中最多只有一个activity,否则栈底的activity将不能被多次创建并销毁。由于“不保留活动”开发者选项的勾选以及“–activity-clear-task”参数的使用,使得每当一个新的activity被启动时,该应用原先启动的activity将会自动销毁。每个activity可以启动k次(k由用户指定)。
三、为了检测应用构件的泄露,我们需要获取应用在上述反复启动应用不同activity的过程中内存堆栈的内容,该过程主要完成以下功能:
a)若在逐个启动并销毁待测试安卓应用所包含的所有activity的过程中,应用出现异常并崩溃,则自动转储应用当前的堆栈内容,并关闭应用;
b)当逐个启动并销毁待测试安卓应用所包含的所有activity的过程完毕之后,自动转储应用当前的堆栈内容。
四、最终,本方案需要对转储的应用堆栈文件(一系列.hprof文件)进行分析,以最终确定泄露的应用构件,该过程主要包括以下步骤:
a)针对一个转储的应用堆栈.hprof文件,首先获取其中所包含的所有activity对象实例集合,用sa表示;
b)其次,针对所获得的sa中的每一个对象实例obj进行逐个鉴别,判定obj是否已经被销毁,若obj被判定为已销毁,则将其从sa中删除。
c)针对处理后得到的sa中的剩余对象实例obj,进一步判定其是否是泄露的,若是则将其从sa中删除。
d)返回sa,即获得所有泄露的activity
其中,判定一个对象实例obj是否被销毁的主要方法如下:安卓为每一个activity实例维护了一个名为mdestroyed的域来指明该实例是否已经被销毁(destroyed)。所以,若obj∈sa,则直接依据obj的mdestroyed域的值来判断obj是否已经被销毁(obj.mdestroyed=true则表示obj已经被销毁);
而要进一步判定一个被销毁的对象实例obj是否泄露,则需要完成以下步骤:
a)获取对象obj到达所有gcroot的路径所构成的集合,记为lp;
b)从lp中去除不影响obj是否能被gc回收的路径——即所有包含java.lang.ref.softreference、java.lang.ref.weakreference、java.lang.ref.phantomreference、java.lang.ref.finalizerreference以及java.lang.ref.finalizer类型对象的路径;
c)若最后lp为空,则obj不是泄露的;否则,obj则是泄露的。
本发明能够自动化地实现以下功能:逐个启动并销毁待检测安卓应用的各个activity,收集安卓应用堆栈内容,并通过进一步分析所转储的应用堆栈内容,鉴别泄露activity构件实例。相对现有其他工作而言,本发明具有以下有益效果:
1)自动化;
2)高效率;
3)可重现。
附图说明
图1为本发明实施例的基于安卓应用多入口特性的activity泄露检测方法的整体流程框架。
图2为本发明实施例的自动启动、销毁应用activity并转储应用堆栈的流程图。
图3为本发明实施例的分析堆栈文件识别泄露activity的流程。
具体实施方式
下面结合本发明实例中的附图,对本发明实施例中的技术方案进行清楚、完整地的描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部实施例。基于本发明的实施例,本领域普通技术人员在没有做出创造性劳动的前提下所获得的所有其他实施例,都属于本发明的保护范围。
1.主要过程
图1所示为本发明提供的一种基于安卓应用多入口特性的activity泄露检测方法的整体流程框架图,图1中:
对于待检测的一个安卓应用,我们首先将设备的开发者选项的“不保留活动”这一选项打开,以迫使系统及时自动销毁所有用户不可见的活动(activity);然后,安装待检测应用;再然后,则尝试逐个启动、销毁待检测应用所包含的activity并转储应用运行时刻堆栈;最后,利用内存分析工具分析转储的堆栈文件,以确定泄露的activity实例。
图2所示为本发明中自动启动、销毁应用activity并转储应用堆栈的流程图。首先,利用逆向工程工具反编译待检测应用(apk文件),获取应用的androidmenifest.xml文件,并进一步分析该文件获取应用所包含的所有activity类名,存放在lactivity列表中;接下来,针对lactivity中的每一个activity类,尝试利用“amstart-n”命令(带参数“—activity-clear-task”)来自动创建该类activity实例k次。由于“不保留活动”选项的打开以及“—activity-clear-task”参数的使用,导致新的activity实例一旦被创建并显示,则原先所显示的activity实例则会自动的尝试销毁。若在上述过程中,应用出错并崩溃,则自动转储应用当前的堆栈内容。当lactivity中的所有activity类都完成创建、销毁实例k次之后,最后再转储应用的堆栈内容。
图3所示为本发明中自动化分析堆栈文件(即.hprof文件),并进一步鉴别泄露activity实例的流程。针对每一个待分析的堆栈文件(即.hprof文件),首先找出其中所包含的所有的activity实例,存放在列表sa之中;接下来,遍历sa的每一个实例obj,若obj.mdestroyed=false,则将obj从sa中删除,从而sa中仅包含obj.mdestroyed=true的activity实例,即被销毁了的实例;
再然后,则要逐个判断剩余在sa的每一个实例obj是否真是泄露的,而这是通过对obj到达所有gcroot的路径进行分析而得到的。简单而言,首先需要获取obj到达所有gcroot的路径的集合,记为lp;逐一处理lp中的每一条路径p,若路径p包含任何java.lang.ref.softreference、java.lang.ref.weakreference、java.lang.ref.phantomreference、java.lang.ref.finalizerreference以及java.lang.ref.finalizer类型对象,则将路径p从lp中删除。当lp中所有路径都处理完毕,若lp为空,则判定实例obj不是泄露的实例,而是有可能会被gc回收的;否则,lp不为空,则实例obj仍在某些地方被引用而不能被gc回收,从而判定实例obj为泄露的实例。
以上的实施例仅为说明本发明的技术思想,不能以此限定本发明的保护范围,凡是按照本发明提出的技术思想,在技术方案基础上所做的任何改动,均落入本发明保护范围之内。本发明未涉及的技术均可通过现有的技术加以实现。