提取程序无响应发生时函数栈的提取方法和装置
技术领域
本申请涉及移动终端技术领域,特别涉及一种提取程序无响应发生时函数栈的提取方法和装置。
背景技术
通常,在Android(安卓)***中,如果应用程序有一段时间响应不灵敏,***会向用户显示一个对话框,这个对话框被称作应用程序无响应(Application Not Responding,简称ANR)对话框,用户可以选择该对话框上的“等待”按钮而让程序继续运行,也可以选择该对话框上的“强制关闭”按钮来中断程序的运行。因此,在每次出现ANR的情况时,用户都要对应用程序无响应对话框进行处理,从而造成用户的体验感变差。
为了提升用户体验,设计流畅合理的应用程序成为必要。开发人员在开发应用程序时,需要通过抓取应用程序无响应来完善该应用程序。相关技术中,抓取应用程序无响应(即ANR)的方法主要是:可先抓取出移动终端(如手机等)上/data/anr目录下的traces.txt文件(即应用程序错误信息反馈文件),之后,通过人工分析该文件里面的函数栈信息,找出属于某个应用程序的ANR。
但是存在的问题是,上述抓取ANR的方法,流程比较复杂,并且整个抓取过程主要都是通过人工来操作,增加了开发人员的工作量,增加了人工成本,且效率低。
发明内容
本申请的目的旨在至少在一定程度上解决上述的技术问题之一。
为此,本申请的第一个目的在于提出了一种提取程序无响应发生时函数栈的提取方法。该方法通过跨线程之间的交互来实现程序无响应发生时主线程中函数栈的提取,整个提取过程完全自动化,无需人工参与,降低了开发人员的工作量,降低了人工成本,提高了效率。
本申请的第二个目的在于提出了一种提取程序无响应发生时函数栈的提取装置。
为达上述目的,根据本申请第一方面的实施例提出了一种提取程序无响应发生时函数栈的提取方法,包括以下步骤:建立子线程,并通过所述子线程建立第一变量和第二变量,其中,所述第二变量等于所述第一变量;所述子线程发送任务至主线程,其中,所述任务用于在被所述主线程执行时修改所述第一变量;所述子线程在预设时间之后判断所述第一变量和第二变量是否相等;以及如果所述第一变量和第二变量相等,则所述子线程判断所述任务未被所述主线程执行而导致程序无响应,并提取所述主线程当前的函数栈。
本申请实施例的提取程序无响应发生时函数栈的提取方法,可建立子线程,并通过子线程发送任务至主线程,并在预设时间后子线程判断任务有无被主线程执行,如果判断出上述任务没有被主线程执行则提取上述主线程当前的函数栈,即通过跨线程之间的交互来实现程序无响应发生时主线程中函数栈的提取,整个提取过程完全自动化,无需人工参与,降低了开发人员的工作量,降低了人工成本,提高了效率,并且通过将提取到的函数栈提交到移动后台,方便了开发人员发现并解决问题。
为达上述目的,根据本申请的第二方面的实施例提出了一种提取程序无响应发生时函数栈的提取装置,包括:建立模块,用于建立子线程,并通过所述子线程建立第一变量和第二变量,其中,所述第二变量等于所述第一变量;子线程控制模块,其中,所述子线程控制模块包括:任务发送子模块,用于发送任务至主线程,其中,所述任务用于在被所述主线程执行时修改所述第一变量;判断子模块,用于在预设时间之后判断所述第一变量和第二变量是否相等;以及提取子模块,用于在所述第一变量和第二变量相等时,判断所述任务未被所述主线程执行而导致程序无响应,并提取所述主线程当前的函数栈。
本申请实施例的提取程序无响应发生时函数栈的提取装置,可通过建立模块建立子线程,并通过子线程控制模块中的任务发送子模块发送任务至主线程,并在预设时间后判断子模块判断任务有无被主线程执行,如果判断出上述任务没有被主线程执行则通过提取子模块提取上述主线程当前的函数栈,即通过跨线程之间的交互来实现程序无响应发生时主线程中函数栈的提取,整个提取过程完全自动化,无需人工参与,降低了开发人员的工作量,降低了人工成本,提高了效率,并且通过将提取到的函数栈提交到移动后台,方便了开发人员发现并解决问题。
本申请附加的方面和优点将在下面的描述中部分给出,部分将从下面的描述中变得明显,或通过本申请的实践了解到。
附图说明
本申请的上述和/或附加的方面和优点从结合下面附图对实施例的描述中将变得明显和容易理解,其中:
图1是根据本申请一个实施例的提取程序无响应发生时函数栈的提取方法的流程图;
图2是根据本申请一个具体实施例的提取程序无响应发生时函数栈的提取方法的示例图;
图3是根据本申请另一个具体实施例的提取程序无响应发生时函数栈的提取方法的流程图;
图4是根据本申请一个实施例的提取程序无响应发生时函数栈的提取装置的结构框图;以及
图5是根据本申请另一个实施例的提取程序无响应发生时函数栈的提取装置的结构框图。
具体实施方式
下面详细描述本申请的实施例,所述实施例的示例在附图中示出,其中自始至终相同或类似的标号表示相同或类似的元件或具有相同或类似功能的元件。下面通过参考附图描述的实施例是示例性的,旨在用于解释本申请,而不能理解为对本申请的限制。
下面参考附图描述本申请实施例的提取程序无响应发生时函数栈的提取方法和装置。
图1是根据本申请一个实施例的提取程序无响应发生时函数栈的提取方法的流程图。需要说明的是,本申请实施例的提取程序无响应发生时函数栈的提取方法适用于具有Android操作***的移动终端,该移动终端可以是手机、平板电脑、个人数字助理等硬件设备。此外,上述程序可以是安装在移动终端上的应用程序,为了方便描述,后续实施例中将以测试应用程序进行描述。
如图1所示,该提取程序无响应发生时函数栈的提取方法,包括以下步骤:
S110,建立子线程,并通过子线程建立第一变量和第二变量,其中,第二变量等于第一变量。
具体地,在本申请的一个实施例中,假设本申请实施例的提取方法应用于具有Android操作***的移动终端上,当测试应用程序第一次启动时,移动终端可针对该测试应用程序建立一个对应的子线程,并且通过该子线程建立第一变量index和第二变量lastIndex,并将第二变量lastIndex等于第一变量index。例如,可将第一变量index赋初始值,然后将第二变量lastIndex的值等于第一变量index的初始值。
优选地,为了保证第一变量index在多线程访问时不被其他线程影响,在本申请的一个实施例中,在通过子线程建立第一变量之后,还可将该第一变量的属性设置为不稳定变量属性值Volatile,以便于接下来对第一变量的修改。需要说明的是,通过将第一变量属性值设置为Volatile,可以保证第一变量在多线程访问时不被其他线程所影响,Volatile是一个类型修饰符,它用来修饰被不同线程访问和修改的变量,在本申请的实施例中,将第一变量的属性值设置为Volatile相当于告诉***这个变量可能会被意想不到的改变,这样***的编译器就不会去假设这个变量的值,也就是说,***的优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,可以理解通过将第一变量的属性值设置为Volatile,可以保证第一变量的值能准确反映应用程序的线程有无被主线程执行,也就是说只要检测到第一变量值变化,就代表对应的子线程被主线程执行,同时,只要第一变量值没有发生变化,就代表对应的子线程没有被主线程执行。
S120,子线程发送任务至主线程,其中,上述任务用于在被主线程执行时修改第一变量。
可以理解,该主线程可以是在测试应用程序启动时,Android操作***会启动一个该测试应用程序对应的线程,该主线程主要负责处理该测试应用程序中与UI(UserInterface,用户界面)相关的事件,例如,用户的按键事件、用户接触屏幕的事件以及屏幕绘图事件等,并将相关的事件分发到对应的组件进行处理。
具体地,在建立测试应用程序对应的子线程之后,该子线程可通过post方法发送任务至该测试应用程序对应的主线程,该任务可用于在被主线程执行时修改第一变量,该任务可理解为一串代码的集合。
其中,在本申请的实施例中,任务在被主线程执行时使得第一变量加1之后取余。具体地,主线程在执行该任务时,该任务可根据自身代码集合对第一变量的值进行修改,即每当被主线程执行时会将第一变量的值加1之后取余,例如,可将第一变量的值加1之后与常量10进行取余,并将该取余得到的余数赋给第一变量。可以理解,这里取余是为了保持第一变量的值始终处于一定范围内(即处于比较小的数),如0-9的范围内,这样使得任务在执行时不会发生溢出,避免了因溢出导致第一变量被重置从而导致接下来判断不准确的情况发生。
例如,子线程可通过post方法发送一个任务Runnable,在该任务Runnable中定义了一些代码集合,可用于在被主线程执行时对第一变量index加1之后与常量10进行取余,并将余数赋给第一变量index,即index=(index+1)%10。其中,上述的post方法指的是一种向目的服务器发送更新请求,并附有请求实体的一种方法,比如用来上传文件、将表格的结果提交给数据处理过程等,在本申请的实施例中,post方法可用来将子线程发送的任务发送到主线程。
需要说明的是,如果主线程执行子线程发送的任务,那么上述任务就会对第一变量进行修改,可以理解第一变量如果被修改那么就代表主线程执行了子线程发送的任务。
还需要说明的是,在本申请的一个实施例中,上述任务在被主线程执行时,还可用于控制子线程休眠预设时间。其中,在本申请的实施例中,由于在默认情况下,Android操作***中Activity的最长执行时间一般为5s,所以可将预设时间设定为5s。可以理解,还可根据实际测试应用程序的情况而设定该预设时间的值。也就是说,任务在被主线程执行时,在修改第一变量的同时,还可控制子线程sleep5秒,以为该任务能够被主线程执行提供一定的时间。
S130,子线程在预设时间之后判断第一变量和第二变量是否相等。
具体地,在控制子线程休眠预设时间之后,子线程可判断此时的第一变量的值和第二变量的值是否相等。
S140,如果第一变量和第二变量相等,则子线程判断任务未被主线程执行而导致程序无响应,并提取主线程当前的函数栈。
具体地,如果在子线程休眠预设时间后,子线程判断此时的第一变量和第二变量相等,则可判断子线程发送给主线程的任务未被主线程执行而导致程序无响应,这样可以判定主线程肯定是被某个函数阻塞住而没有执行上述任务,这时可提取主线程当前的函数栈。
优选地,在提取主线程当前的函数栈之后,可将该函数栈上传至服务器端并记录下来,以供开发人员发现并解决问题。
举例而言,如图2所示,当测试应用程序启动时,移动终端可建立一个该测试应用程序对应的子线程,并通过子线程建立第一变量index,其中将第一变量index设置为volatile属性,并建立第二变量lastIndex,使得第二变量lastIndex等于第一变量index。之后,子线程可通过post方法发送一个任务Runnable到该测试应用程序的主线程中,其中,在Runnable中,可以让index+1取余,即index=(index+1)%10,同时控制子线程sleep5秒。在子线程sleep5秒之后,子线程可判断第二变量lastIndex和第一变量index是否相等,如果相等,则说明post到主线程的Runnable并没有被主线程执行,这样可以判断主线程可能是被某个函数阻塞住了而没有被执行,这时候可以捕获出主线程当前的函数栈并将其上传到服务端后台记录下来。
本申请实施例的提取程序无响应发生时函数栈的提取方法,可建立子线程,并通过子线程发送任务至主线程,并在预设时间后子线程判断任务有无被主线程执行,如果判断出上述任务没有被主线程执行则提取上述主线程当前的函数栈,即通过跨线程之间的交互来实现程序无响应发生时主线程中函数栈的提取,整个提取过程完全自动化,无需人工参与,降低了开发人员的工作量,降低了人工成本,提高了效率,并且通过将提取到的函数栈提交到移动后台,方便了开发人员发现并解决问题。
图3是根据本申请一个具体实施例的提取程序无响应发生时函数栈的提取方法的流程图。
如图3所示,本申请实施例的提取程序无响应发生时函数栈的提取方法,包括:
S310,建立子线程,并通过子线程建立第一变量和第二变量,其中,第二变量等于第一变量。
S320,子线程发送任务至主线程,其中,上述任务用于在被主线程执行时修改第一变量。
S330,子线程在预设时间之后判断第一变量和第二变量是否相等。
S340,如果第一变量和第二变量相等,则子线程判断任务未被主线程执行而导致程序无响应,并提取主线程当前的函数栈。
S350,如果第一变量和第二变量不相等,则子线程判断任务已被主线程执行。
具体而言,在本申请的实施例中,如果子线程判断出第一变量和第二变量不相等,子线程判断任务已经被主线程执行。即在子线程发送给主线程任务后,主线程在执行该任务时,可通过该任务使得第一变量加1之后与常量10取余,并将余数赋给第一变量,从而使得第一变量发生了变化,子线程在休眠预设时间之后,判断此时的第一变量和第二变量不相等,从而判断出任务已经被主线程执行。
本申请实施例的提取程序无响应发生时函数栈的提取方法,子线程在预设时间后判断第一变量和第二变量不相等时,判断任务已被主线程执行,从而实现了对程序有无响应的快速判断,方便了开发人员对应用程序运行情况的了解。
为了实现上述实施例,本申请还提出了一种提取程序无响应发生时函数栈的提取装置。
图4是根据本申请一个实施例的提取程序无响应发生时函数栈的提取装置的结构框图。需要说明的是,本申请实施例的提取程序无响应发生时函数栈的提取装置适用于具有Android操作***的移动终端,该移动终端可以是手机、平板电脑、个人数字助理等硬件设备。
如图4所示,该提取程序无响应发生时函数栈的提取装置,包括:建立模块410和子线程控制模块420。
具体地,建立模块410可用于建立子线程,并通过子线程建立第一变量和第二变量,其中,第二变量等于第一变量。
更具体地,在本申请的一个实施例中,假设本申请实施例的提取装置应用于具有Android操作***的移动终端上,当测试应用程序启动时,建立模块410可针对该测试应用程序建立一个对应的子线程,并且通过该子线程建立第一变量index和第二变量lastIndex,并将第二变量lastIndex等于第一变量index。例如,可将第一变量index赋初始值,然后将第二变量lastIndex的值等于第一变量index的初始值。
在本申请的实施例中,如图4所示,子线程控制模块420可包括:任务发送子模块421、判断子模块422和提取子模块423。
具体地,任务发送子模块421可用于发送任务至主线程,其中,上述任务用于在被主线程执行时修改第一变量。
可以理解,该主线程可以是在测试应用程序启动时,Android操作***会启动一个该测试应用程序对应的线程,该主线程主要负责处理该测试应用程序中与UI(UserInterface,用户界面)相关的事件,例如,用户的按键事件、用户接触屏幕的事件以及屏幕绘图事件等,并将相关的事件分发到对应的组件进行处理。
更具体地,在建立模块410建立测试应用程序对应的子线程之后,任务发送子模块421可通过post方法发送任务至该测试应用程序对应的主线程,该任务可用于在被主线程执行时修改第一变量,该任务可理解为一串代码的集合。其中,在本申请的实施例中,任务在被主线程执行时使得第一变量加1之后取余。具体地,主线程在执行该任务时,该任务可根据自身代码集合对第一变量的值进行修改,即每当被主线程执行时会将第一变量的值加1之后取余,例如,可将第一变量的值加1之后与常量10进行取余,并将该取余得到的余数赋给第一变量。可以理解,这里取余是为了保持第一变量的值始终处于一定范围内(即处于比较小的数),如0-9的范围内,这样使得任务在执行时不会发生溢出,避免了因溢出导致第一变量被重置从而导致接下来判断不准确的情况发生。
例如,任务发送子模块421可通过post方法发送一个任务Runnable,在该任务Runnable中定义了一些代码集合,可用于在被主线程执行时对第一变量index加1之后与常量10进行取余,并将余数赋给第一变量index,即index=(index+1)%10。其中,上述的post方法指的是一种向目的服务器发送更新请求,并附有请求实体的一种方法,比如用来上传文件、将表格的结果提交给数据处理过程等,在本申请的实施例中,post方法可用来将子线程发送的任务发送到主线程。需要说明的是,如果主线程执行任务发送子模块421发送的任务,那么上述任务就会对第一变量进行修改,可以理解第一变量如果被修改那么就代表主线程执行了任务发送子模块421发送的任务。
还需要说明的是,在本申请的一个实施例中,上述任务在被主线程执行时,还可用于控制子线程休眠预设时间。其中,在本申请的实施例中,由于在默认情况下,Android操作***中Activity的最长执行时间一般为5s,所以可将预设时间设定为5s。可以理解,还可根据实际测试应用程序的情况而设定该预设时间的值。也就是说,任务在被主线程执行时,在修改第一变量的同时,还可控制子线程sleep5秒,以为该任务能够被主线程执行提供一定的时间。
判断子模块422可用于在预设时间之后判断第一变量和第二变量是否相等。
更具体地,在任务控制子线程休眠预设时间之后,判断子模块422可判断此时的第一变量和第二变量的值是否相等。
可以理解,在本申请的实施例中,判断子模块422还可用于在第一变量和第二变量不相等时,判断任务已被主线程执行。具体而言,判断子模块422在判断出第一变量和第二变量不相等时,可判断任务已经被主线程执行。即在任务发送子模块421发送给主线程任务后,主线程在执行该任务时,可通过该任务使得第一变量加1之后与常量10取余,并将余数赋给第一变量,从而使得第一变量发生了变化,子线程在休眠预设时间之后,判断子模块422判断此时的第一变量和第二变量不相等,从而判断出任务已经被主线程执行。由此,实现了对程序有无响应的快速判断,方便了开发人员对应用程序运行情况的了解。
提取子模块423可用于在第一变量和第二变量相等时,判断任务未被主线程执行而导致程序无响应,并提取主线程当前的函数栈。
更具体地,如果在子线程休眠预设时间后,判断子模块422判断此时的第一变量和第二变量相等,则可判断子线程发送给主线程的任务未被主线程执行而导致程序无响应,这样可以判定主线程肯定是被某个函数阻塞住而没有执行上述任务,这时提取子模块423可提取主线程当前的函数栈。
优选地,提取子模块423在提取主线程当前的函数栈之后,可将该函数栈上传至服务器端并记录下来,以供开发人员发现并解决问题。
为了保证第一变量index在多线程访问时不被其他线程影响,优选地,在本申请的一个实施例中,如图5所示,在建立模块410通过子线程建立第一变量之后,该提取装置还包括设置模块430,设置模块430可将该第一变量的属性设置为不稳定变量属性值Volatile,以便于上述任务发送子模块421发送的任务被主线程执行时对第一变量的修改。需要说明的是,通过设置模块430将第一变量属性值设置为Volatile,可以保证第一变量在多线程访问时不被其他线程所影响,Volatile是一个类型修饰符,它用来修饰被不同线程访问和修改的变量,在本申请的实施例中,将第一变量的属性值设置为Volatile相当于告诉***这个变量可能会被意想不到的改变,这样***的编译器就不会去假设这个变量的值,也就是说,***的优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,可以理解通过将第一变量的属性值设置为Volatile,可以保证第一变量的值能准确反映应用程序的线程有无被主线程执行,也就是说只要检测到第一变量值变化,就代表对应的子线程被主线程执行,同时,只要第一变量值没有发生变化,就代表对应的子线程没有被主线程执行。本申请实施例的提取程序无响应发生时函数栈的提取装置,可通过建立模块建立子线程,并通过子线程控制模块中的任务发送子模块发送任务至主线程,并在预设时间后判断子模块判断任务有无被主线程执行,如果判断出上述任务没有被主线程执行则通过提取子模块提取上述主线程当前的函数栈,即通过跨线程之间的交互来实现程序无响应发生时主线程中函数栈的提取,整个提取过程完全自动化,无需人工参与,降低了开发人员的工作量,降低了人工成本,提高了效率,并且通过将提取到的函数栈提交到移动后台,方便了开发人员发现并解决问题。
在本申请的描述中,需要理解的是,术语“第一”、“第二”仅用于描述目的,而不能理解为指示或暗示相对重要性或者隐含指明所指示的技术特征的数量。由此,限定有“第一”、“第二”的特征可以明示或者隐含地包括至少一个该特征。在本申请的描述中,“多个”的含义是至少两个,例如两个,三个等,除非另有明确具体的限定。
在本说明书的描述中,参考术语“一个实施例”、“一些实施例”、“示例”、“具体示例”、或“一些示例”等的描述意指结合该实施例或示例描述的具体特征、结构、材料或者特点包含于本申请的至少一个实施例或示例中。在本说明书中,对上述术语的示意性表述不必须针对的是相同的实施例或示例。而且,描述的具体特征、结构、材料或者特点可以在任一个或多个实施例或示例中以合适的方式结合。此外,在不相互矛盾的情况下,本领域的技术人员可以将本说明书中描述的不同实施例或示例以及不同实施例或示例的特征进行结合和组合。
流程图中或在此以其他方式描述的任何过程或方法描述可以被理解为,表示包括一个或更多个用于实现特定逻辑功能或过程的步骤的可执行指令的代码的模块、片段或部分,并且本申请的优选实施方式的范围包括另外的实现,其中可以不按所示出或讨论的顺序,包括根据所涉及的功能按基本同时的方式或按相反的顺序,来执行功能,这应被本申请的实施例所属技术领域的技术人员所理解。
应当理解,本申请的各部分可以用硬件、软件、固件或它们的组合来实现。在上述实施方式中,多个步骤或方法可以用存储在存储器中且由合适的指令执行***执行的软件或固件来实现。例如,如果用硬件来实现,和在另一实施方式中一样,可用本领域公知的下列技术中的任一项或他们的组合来实现:具有用于对数据信号实现逻辑功能的逻辑门电路的离散逻辑电路,具有合适的组合逻辑门电路的专用集成电路,可编程门阵列(PGA),现场可编程门阵列(FPGA)等。
本技术领域的普通技术人员可以理解实现上述实施例方法携带的全部或部分步骤是可以通过程序来指令相关的硬件完成,所述的程序可以存储于一种计算机可读存储介质中,该程序在执行时,包括方法实施例的步骤之一或其组合。
此外,在本申请各个实施例中的各功能单元可以集成在一个处理模块中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个模块中。上述集成的模块既可以采用硬件的形式实现,也可以采用软件功能模块的形式实现。所述集成的模块如果以软件功能模块的形式实现并作为独立的产品销售或使用时,也可以存储在一个计算机可读取存储介质中。
上述提到的存储介质可以是只读存储器,磁盘或光盘等。尽管上面已经示出和描述了本申请的实施例,可以理解的是,上述实施例是示例性的,不能理解为对本申请的限制,本领域的普通技术人员在本申请的范围内可以对上述实施例进行变化、修改、替换和变型。