一种内存检测方法及装置
技术领域
本公开涉及计算机技术领域,具体而言,涉及一种内存检测方法及装置。
背景技术
在应用程序运行时,需要将应用程序的文件加载到终端设备的内存中,终端设备需要通过操作系统的虚拟内存模块为应用程序分配相应的虚拟内存。在应用程序运行中时,可能会出现内存溢出(Out Of Memory,OOM)的问题,出现内存溢出的原因可能是终端设备已经使用的内存过多,也有可能是终端设备的其他一些进程使用了内存后没有及时释放,导致可用的内存不足。
内存溢出会导致应用程序被立刻关闭,无法正常工作,因此,内存溢出原因排查也十分重要。内存溢出的排查需要通过对内存进行检测实现。
发明内容
本公开实施例至少提供一种内存检测方法及装置。
第一方面,本公开实施例提供了一种内存检测方法,包括:
获取目标应用程序对应的内存节点的属性信息;所述属性信息包括内存节点的内存尺寸和地址信息;
基于所述内存节点的属性信息,获取所述内存节点的符号化信息,以及内存节点之间的引用关系信息;所述符号化信息用于表征所述内存节点的用途;
将所述内存节点的属性信息、所述符号化信息、和所述引用关系信息作为内存状态信息;所述内存状态信息用于定位内存故障。
第二方面,本公开实施例还提供另一种内存检测方法,包括:
获取终端设备上报的内存状态信息,所述内存状态信息包括目标应用程序对应的当前存活的内存节点的属性信息、符号化信息和引用关系信息;所述符号化信息用于表征所述内存节点的用途;
基于所述内存节点的内存状态信息,确定发生异常的内存节点的异常信息;
基于所述异常信息,针对发生异常的内存节点进行问题聚类,确定至少一种问题类型。
第三方面,本公开实施例还提供了一种内存检测装置,包括:
第一获取模块,用于获取目标应用程序对应的内存节点的属性信息;所述属性信息包括内存节点的内存尺寸和地址信息;
第二获取模块,用于基于所述内存节点的属性信息,获取所述内存节点的符号化信息,以及内存节点之间的引用关系信息;所述符号化信息用于表征所述内存节点的用途;
信息确定模块,用于将所述内存节点的属性信息、所述符号化信息、和所述引用关系信息作为内存状态信息;所述内存状态信息用于定位内存故障。
第四方面,本公开实施例还提供了另一种内存检测装置,包括:
第三获取模块,用于获取终端设备上报的内存状态信息,所述内存状态信息包括目标应用程序对应的当前存活的内存节点的属性信息、符号化信息和引用关系信息;所述符号化信息用于表征所述内存节点的用途;
第一确定模块,用于基于所述内存节点的内存状态信息,确定发生异常的内存节点的异常信息;
第二确定模块,用于基于所述异常信息,针对发生异常的内存节点进行问题聚类,确定至少一种问题类型。
第五方面,本公开实施例还提供一种计算机设备,包括:处理器、存储器和总线,所述存储器存储有所述处理器可执行的机器可读指令,当计算机设备运行时,所述处理器与所述存储器之间通过总线通信,所述机器可读指令被所述处理器执行时执行上述第一方面,或第二方面中任一种可能的实施方式中的步骤。
第六方面,本公开实施例还提供一种计算机可读存储介质,该计算机可读存储介质上存储有计算机程序,该计算机程序被处理器运行时执行上述第一方面第二方面中任一种可能的实施方式中的步骤。
关于上述内存检测装置、计算机设备、及计算机可读存储介质的效果描述参见上述内存检测方法的说明,这里不再赘述。
本公开实施例提供的内存检测方法及装置,能够获取目标应用程序对应的内存节点的属性信息,并根据属性信息确定内存节点的符号化信息和不同内存节点之间的引用关系信息,在将内存节点的属性信息、内存节点的符号化信息及引用关系信息作为内存状态信息,内存状态信息用于定位内存故障;也即,本公开实施例不需要记录内存分配的堆栈,也能获取到对内存节点进行问题分析定位的数据,可以避免因频繁记录内存分配的堆栈导致设备性能损耗过大的问题,有效节省内存检测所占用的计算资源;另外,基于反映内存节点用途的符号化信息和不同内存节点之间的引用关系信息,可以更全面地定位内存节点出现的问题。
为使本公开的上述目的、特征和优点能更明显易懂,下文特举较佳实施例,并配合所附附图,作详细说明如下。
附图说明
为了更清楚地说明本公开实施例的技术方案,下面将对实施例中所需要使用的附图作简单地介绍,此处的附图被并入说明书中并构成本说明书中的一部分,这些附图示出了符合本公开的实施例,并与说明书一起用于说明本公开的技术方案。应当理解,以下附图仅示出了本公开的某些实施例,因此不应被看作是对范围的限定,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他相关的附图。
图1示出了本公开实施例所提供的一种内存检测系统的示意图;
图2示出了本公开实施例所提供的一种内存检测方法的流程图;
图3示出了本公开实施例所提供的另一种内存检测方法的流程图;
图4示出了本公开实施例所提供的内存检测方法中,引用图的示意图;
图5示出了本公开实施例所提供的内存检测方法中,支配树的示意图;
图6示出了本公开实施例所提供的一种内存检测装置的示意图;
图7示出了本公开实施例所提供的另一种内存检测装置的示意图;
图8示出了本公开实施例所提供的一种计算机设备的示意图;
图9示出了本公开实施例所提供的另一种计算机设备的示意图。
具体实施方式
为使本公开实施例的目的、技术方案和优点更加清楚,下面将结合本公开实施例中附图,对本公开实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本公开一部分实施例,而不是全部的实施例。通常在此处附图中描述和示出的本公开实施例的组件可以以各种不同的配置来布置和设计。因此,以下对在附图中提供的本公开的实施例的详细描述并非旨在限制要求保护的本公开的范围,而是仅仅表示本公开的选定实施例。基于本公开的实施例,本领域技术人员在没有做出创造性劳动的前提下所获得的所有其他实施例,都属于本公开保护的范围。
经研究发现,想要排查出内存溢出的原因,需要先获取发生内存溢出时应用程序的内存使用情况,才能对内存溢出的原因进行分析,为了获取内存的使用情况,通常需要在应用程序运行期间持续记录内存分配的堆栈,并根据堆栈记录的信息对各个内存节点进行分析,进行内存溢出原因的排查,这种方式需要消耗较多的计算资源在记录堆栈信息上,在应用程序正常运行时也会记录堆栈信息,影响应用程序的正常使用,且会产生大量的数据,这些数据在多数情况是没有意义的,不利于进行问题的分析。
基于上述研究,本公开提供了一种内存检测方法,能够在检测到目标应用程序满足预设的内存状态信息采集触发条件时,获取目标应用程序对应的当前存活节点的属性信息,并根据属性信息确定不同内存节点之间的引用关系信息,在将内存节点的属性信息和引用关系信息上报给服务器,通过服务器对应用程序的内存信息进行分析,不需要持续性的获取内存的堆栈信息,也能获取到对内存进行分析的数据,可以有效降低内存检测所占用的计算资源,另外,基于反映内存节点用途的符号化信息和不同内存节点之间的引用关系信息,可以实现更全面地定位内存节点出现的问题类型。
针对以上方案所存在的缺陷,均是发明人在经过实践并仔细研究后得出的结果,因此,上述问题的发现过程以及下文中本公开针对上述问题所提出的解决方案,都应该是发明人在本公开过程中对本公开做出的贡献。
应注意到:相似的标号和字母在下面的附图中表示类似项,因此,一旦某一项在一个附图中被定义,则在随后的附图中不需要对其进行进一步定义和解释。
为便于对本实施例进行理解,首先对本公开实施例所公开的一种内存检测系统进行详细介绍。参见图1所示,为本公开实施例提供的内存检测系统,内存检测系统可以包括终端设备以及服务器,终端设备与服务器可以为具有一定计算能力的计算设备,并且终端设备与服务器之间可以进行通信,终端设备上可以运行应用程序,还可以针对应用程序进行内存检测,并将获取到的内存节点相关的信息上报至服务器,服务器可以对终端设备上报的信息进行分析处理。其中,终端设备可以为用户设备(User Equipment,UE)、移动设备、用户终端、终端、蜂窝电话、无绳电话、个人数字处理(Personal Digital Assistant,PDA)、手持设备、计算设备、车载设备、可穿戴设备等。
参见图2所示,为本公开实施例提供的内存检测方法的流程图,所述方法包括步骤S201~S203,其中:
S201:获取目标应用程序对应的内存节点的属性信息;所述属性信息包括内存节点的内存尺寸和地址信息。
这里,目标应用程序对应的内存节点可以为目标应用程序当前存活的内存节点。在获取目标应用程序对应的当前存活的内存节点的属性信息之前,为了保证获取的属性信息不在获取时发生改变,需要将应用程序的其他线程挂起,仅留下负责采集属性信息的线程正常运行。
该步骤中,终端设备可以周期性地对目标应用程序进行检测,当检测到所述目标应用程序满足以下内存状态信息采集触发条件时,获取所述目标应用程序对应的内存节点的属性信息;其中,所述内存状态信息采集触发条件包括以下至少一项:
所述目标应用程序的占用内存大于预设的检测阈值;
在最近预设时间段内,没有触发过内存状态信息的采集;
在预设的时间周期内,采集内存状态信息的次数小于预设次数;
内存状态信息采集模块占用的存储空间大小小于设定阈值。
示例性的,检测阈值可以根据终端设备的内存上限值设定,比如,若终端设备的内存上限为2GB,则可以将检测阈值设置为1GB,在应用程序占用的内存超出检测阈值的情况下,可以认为应用程序处于较危险的状态,容易发生内存溢出。设置预设的时间段内,没有触发过内存状态信息的触发条件,可以防止过于频繁的进行内存状态信息的采集。相似的,在预设的时间周期内,采集内存状态信息的次数小于预设次数,也能够防止频繁的进行内存状态信息的采集。由于内存状态信息采集模块也会占用内存和占用磁盘的运行效率,在进行检测之前,还需要使内存状态信息采集模块自身的储存空间大小小于设定阈值,以确保不会因内存状态信息的采集导致内存不足。比如,设定阈值可以为磁盘占用不超过250MB,占用内存不超过100MB。
进一步的,若内存状态信息采集模块的资源占用超出了设定阈值,则可以在采集内存节点的属性信息后,跳过获取内存节点的引用关系信息的步骤,并将属性信息发送至服务器。
这里,检测目标应用程序是否满足预设的内存状态信息采集触发条件可以包括:
在检测到所述目标应用程序满足内存状态信息采集功能开启的前置条件后,周期性检测所述目标应用程序是否满足预设的内存状态信息采集触发条件;其中,所述前置条件包括以下至少一种:
所述目标应用程序的后台服务器下发了内存状态信息采集功能开启指令;运行所述目标应用程序的终端设备为真实设备;所述终端设备的系统版本高于设定版本;所述终端设备的配置信息满足预设配置条件。
其中,目标应用程序的后台服务器可以向目标应用程序下发内存状态信息采集功能开启指令,在接收到内存状态信息采集功能开启指令后,才能记录目标应用程序的内存状态信息;进一步的,前置条件还可以包括在运行目标应用程序的终端设备为真实设备,当运行目标应用程序的终端设备是模拟器时,模拟器的内存上限通常比较高,不符合真实设备的实际情况,这样可以保证数据的真实性;终端设备的系统版本也可以设置相应的前置条件,若终端设备的系统版本过低,可能会不支持进行内存状态信息的采集,示例性的,设定版本可以设定为iOS系统10.0;再者,还可以为终端设备的配置信息设置预设配置条件,比如,终端设备的中央处理器架构为64位,终端设备的机型高于预设的机型。
这里,终端设备可以是具有iOS系统的计算机设备。
进一步的,所述获取所述目标应用程序对应的当前存活的内存节点的属性信息可以包括:
获取所述目标应用程序对应的虚拟内存节点的属性信息;和/或,获取目标应用程序对应的堆内存节点的属性信息。
该步骤中,针对虚拟内存节点,可以获取所述虚拟内存节点的地址信息、内存尺寸以及用户标签;针对堆内存节点,可以获取所述堆内存节点的地址信息以及内存尺寸。
其中,应用程序的内存都是由虚拟内存组成的,每个单独的虚拟内存可以被称为虚拟内存(Virtual Memory,VM)节点,当前能够检测到的内存节点即为当前存活的内存节点,对于虚拟内存节点,可以利用预先设定好的函数,遍历一进程对应的所有虚拟内存节点,并返回一个结构体,该结构体中包含了虚拟内存节点的属性信息,通过预先设定的解析函数可以将属性信息从结构体中解析出来。
具体的,虚拟内存节点的属性信息可以包括虚拟内存节点的地址信息、内存尺寸以及用户标签。通过虚拟内存节点的地址信息、内存尺寸,可以对该虚拟内存节点进行访问,通过虚拟内存节点的用户标签,可以了解该虚拟内存节点的用途。
进一步的,为了避免所有的内存分配都通过系统调用而产生性能不足的问题,一些库在申请内存时,会申请一大块内存,并在申请到的大块内存中由库进行内存的二次分配,以实现降低系统运算量的效果,这一大块内存就被称为堆。堆中可以包含多个堆内存节点,本公开实施例中的堆内存以堆中节点粒度存在,可以通过对应的函数对堆中的堆内存节点进行遍历,得到每个堆内存节点的指针与内存尺寸。
其中,内存节点的指针即内存节点的地址信息。
在一种可能的实施方式中,由于需要频繁的扫描内存节点中的信息,需要确定取出的值是否等于某个内存节点的任何一个字节的地址,可以在从除当前内存节点之外的每个内存节点的对应地址范围中搜索查找到的所述数据值,或其他访问内存节点的过程中,针对不同的内存节点分配不同的搜索方式。
具体的,可以根据被搜索的节点的类型,选择不同的搜索方式,比如,可以采用二分法从除当前内存节点之外的每个虚拟内存节点的对应地址范围中搜索所述数据值;若未在虚拟内存节点对应地址范围中搜索到所述数据值,则采用哈希法从除当前内存节点之外的每个堆节点的对应地址范围中搜索所述数据值。
这样,对于数量较少的虚拟内存节点,可以准确的匹配到需要的数据,对于数量较多的堆内存节点,则可以在牺牲一定程度的精准度的前提下,极大程度的提高匹配的效率。
S202:基于所述内存节点的属性信息,获取所述内存节点的符号化信息,以及内存节点之间的引用关系信息;所述符号化信息用于表征所述内存节点的用途。
该步骤中,终端设备可以基于内存节点的地址以及大小,访问内存节点,并从内存节点中获取到内存节点与其他内存节点的引用关系。
示例性的,所述基于所述内存节点的属性信息,获取内存节点之间的引用关系信息,可以包括:
将每个所述内存节点作为当前内存节点,基于所述当前内存节点的地址信息及内存尺寸,从所述当前内存节点的对应地址范围中查找指针格式数据值;
从除所述当前内存节点之外的每个内存节点的对应地址范围中,查找所述指针格式数据值,并根据查找结果确定所述当前内存节点对应的引用关系信息。
这里,在查找数据值的过程中,可以先对正在进行查找的数据进行初步的指针判断,先判断是否符合指针的数据格式,在符合指针的数据格式后再进行查找,这样,可以减少查找过程中的计算量。
该步骤中,可以将每个内存节点作为当前内存节点,并利用当前内存节点对应的地址信息以及内存尺寸,访问当前的内存节点。
这里,在一个内存节点中,会存储自身的引用关系,存储的引用关系通常以指针的形式存在,并存储在预设的字段当中,该字段是一个范围,并不是内存中的一个确定的区域,且指针的数据格式是固定的,因此,可以在指针可能存在的地址范围中搜索指针数据格式数据值,在得到数据值之后,确定该数据值是否是一个有效的内存节点中的任何一个字节的地址,若是,则可以认为该数据值是一个有效的指针。
其中,内存节点除了分为虚拟内存节点和堆内存节点外,还可以通过其他维度进行分类,比如,内存节点可以分为栈内存节点、Objective-C对象内存节点、Swift对象内存节点等。
在内存节点为栈内存节点的情况下,可以通过以下步骤从所述当前内存节点的对应地址范围中查找到至少一个指针格式数据值:
若所述当前内存节点为所述虚拟内存节点中的栈内存节点,则从所述栈内存节点已经使用的栈空间中确定栈指针所在的第一预设位置与栈基础指针所在的第二预设位置;
从所述第一预设位置与所述第二预设位置之间的地址范围内,查找指针格式数据值。
其中,栈内存节点也以虚拟内存节点的形式存在,由于栈上保存了临时变量等数据,可以扫描使用过的栈空间,即可获取到栈内存节点的引用关系信息。
具体的,可以利用先确定栈指针(Stack Pointer)在栈空间中的第一预设位置和栈基础指针(Stack Base Pointer)所在的第二预设位置,第一预设位置与第二预设位置之间的地址范围即该为栈内存节点对应的地址范围,从第一预设位置开始向第二预设位置进行遍历,即向高地址扫描需要的引用关系。
进一步的,对于Objective-C对象或Swift对象的内存节点,由于Swift在内存布局上兼容了Objective-C,可以采用相同的获取方式,可以获取所述当前内存节点的运行信息。若当前内存节点为Objective-C对象或Swift对象,则获取所述当前内存节点的运行信息;若在所述运行信息中查找到目标实例对象,则将所述运行信息中所述目标实例变量的引用关系信息添加到确定的所述当前内存节点的引用关系信息中。
具体的,Objective-C对象或Swift对象的内存节点的运行信息中会含有较详细的引用关系信息,能够详细描述引用关系的类型和符号化信息,示例性的,运行信息中可以包含一个实例对象Ivar,其表示内存节点的引用关系,可以得到该Ivar对象的偏移信息,若与搜索得到的引用关系信息的偏移量一致,则可以利用Ivar对应的信息更新搜索确定的当前内存节点的引用关系。
其中,内存节点的符号化信息可以表征内存节点的用途,用途相同的内存节点可以具有相同的符号化信息,符号化信息能够与属性信息、引用关系信息一同上报给服务器,并在对内存节点的数据进行分析时提供帮助,更容易找出发生异常的内存节点的相同特征,更容易对问题进行定位。
示例性的,若所述内存节点包括虚拟内存节点,所述虚拟内存节点的属性信息还包括用户标签,所述基于所述内存节点的属性信息,获取所述内存节点的符号化信息,包括:
根据所述用户标签,确定所述虚拟内存节点的符号化信息;
和/或,
若所述内存节点包括堆内存节点,所述基于所述内存节点的属性信息,获取所述内存节点的符号化信息,包括:
基于所述内存节点的属性信息,按照预设的对象类型列表,获取所述堆内存节点在所述对象类型列表中任一对象类型下的符号化信息。
该步骤中,由于虚拟内存节点的属性信息中的用户标签(user tag)能够反映虚拟内存节点的用途,因此,可以根据用户标签确定虚拟内存节点的符号化信息,而针对堆内存节点,由于堆内存节点不存在用户标签的概念,因此需要对堆内存节点进行特殊处理。
这里,堆内存节点的对象类型可以包括Objective-C对象、Swift对象、C++对象以及Core Foundation对象。
在所述对象类型包括Objective-C对象和/或Swift对象的情况下,针对Objective-C对象和/或Swift对象,可以通过以下步骤获取符号化信息:
执行所述Objective-C对象和/或Swift对象对应的预设类名获取方法;若执行所述类名获取方法后的返回结果非空,利用预设的实例大小获取接口获取所述返回结果指示的类的最小实例尺寸;基于所述最小实例尺寸,以及所述堆内存节点的内存尺寸,确定所述堆内存节点的类名,并将确定的类名作为所述堆内存节点的所述符号化信息。
具体的,最小实例尺寸也可称为“最小实例大小”、内存尺寸也可称为“内存大小”,表示占用的存储空间大小。预设类名获取方法可以为“object_getClass”,通过预设类名获取方法,可以尝试性的获取一个isa指针,若成功取得了isa指针(isa为一个class类型的变量,也是一个结构体指针),则可以对该指针的真实性进行验证,通过预设的实例大小获取接口获取返回结果指示的类的最小实例大小,若最小实例大小与堆内存节点的大小一致,则可以确定该堆内存节点的对象类型为Objective-C对象或Swift对象,确定预设类名获取方法的返回结果为该堆内存节点的类名,并将该堆内存节点的类名作为其自身对应的符号化信息。
进一步的,在所述对象类型包括C++对象的情况下,针对C++对象,可以通过以下步骤获取符号化信息:
在所述堆内存节点的对应地址范围内,获取所述C++对象对应的第一预设字段中的数据值,该数据值为目标虚函数表的指针;基于所述第一预设字段中的数据值,以及预先生成的映射表,确定所述C++对象对应的目标虚函数表的类名;所述映射表中包含多个虚函数表的指针与虚函数表对应的类名之间的映射关系;将所述目标虚函数表的类名作为所述C++对象的符号化信息。
进一步的,通过以下步骤生成所述映射表:
从所述目标应用程序对应的内存中的第二预设字段中,搜索出至少一个vtable的类名;
基于所述搜索到的vtable的类名,从所述目标应用程序对应的内存中的第三预设字段中,搜索出所述vtable,并获取搜索到的vtable的指针;
建立搜索得到的vtable的类名与vtable的指针之间的映射关系,得到所述映射表。
这里,本公开实施例中的C++对象的内存节点为具有虚函数的C++对象,对于C++对象,可以从C++对象的虚函数表vtable中获取到vtable的类名,并将获取到的类名作为该C++对象的符号化信息。由于无法直接获取所有的vtable,可以先从目标应用程序对应的内存中,存放vtable的类名的第二预设字段中,搜索出可能的vtable的类名,再根据vtable的类名的指针,确定该类名对应的vtable,再建立类名与其对应的vtable的指针之间的对应关系,这样,只要从C++对象的第一预设字段中获取到了其对应的vtable的指针,从映射表中查找该指针对应的vtable的类名,在具体的应用当中,映射表还能够用于判断内存节点是否为C++对象。
在所述对象类型包括Core Foundation对象的情况下,针对Core Foundation对象,可以通过以下步骤获取符号化信息:
在所述堆内存节点的对应地址范围内,查找所述堆内存节点的类名的索引标识;若所述索引标识处于预设的有效参数值范围内,则基于所述索引标识执行CoreFoundation对象对应的预设查询方法,获取所述堆内存节点的类名,并将获取的类名作为所述堆内存节点的所述符号化信息。
其中,Core Foundation对象是Objective-C对象的一种,在通过isa确定此类对象的内存节点的类名时,会统一得到“__NSCFType”这一类名,但这一类名并不是该堆内存节点真实的类名,不能完整的反映出此类堆内存节点的用途,需要再获取能够表示内存节点用途的真正的类名(Core Foundation类名)。
这里,可以先利用索引标识获取函数,获取堆内存节点的类名的索引标识,再根据堆内存节点的类名的索引标识,获取堆内存节点的类名。然而,获取到的类名的索引标识并不全是有效的,若该类名的索引标识已经失效,会导致获取类名的进程崩溃,无法正常运作。
因此,在使用索引标识之前,需要先确定其是否在有效的参数值范围内。
具体的,可以为了确定索引标识是否有效,可以搜索出索引标识对应的“CFRuntime Class Table”这一对象,并根据该对象中每个插槽对应的值,确定索引标识是否在有效参数值范围内,若该对象的与索引标识对应的插槽中的值不为“NULL”,则可以确定索引标识在有效参数范围内,并利用索引标识以及Core Foundation对象对应的预设查询方法,获取堆内存节点的类名,并将确定的类名作为堆内存节点的所述符号化信息。
S203:将所述内存节点的属性信息、所述符号化信息、和所述引用关系信息作为内存状态信息;所述内存状态信息用于定位内存故障。
可以将所述内存节点的属性信息、所述符号化信息、和所述引用关系信息作为内存状态信息,再上报给服务器。
示例性的,在将内存节点的属性信息、符号化信息、和引用关系信息作为内存状态信息上报给服务器之前,可以利用所述目标应用程序的操作系统中的预设写入接口,将所述内存状态信息写入到所述操作系统对应的终端设备的磁盘中。
具体的,预设写入接口可以为mmap映射接口,在内存节点的数据生成后直接写入mmap映射的虚拟内存的尾部,即直接写入目标应用程序的操作系统内存中,并在写入后将先前生成的数据直接销毁,不需要在应用程序中停留,并且,通过延迟上报内存状态信息,可以缓解应用程序的压力。
示例性的,可以在根据所述目标应用程序的后台服务器下发的上报策略,确定当前满足所述上报策略指示的上报触发条件时,将所述内存状态信息上报给服务器。
具体的,上报触发条件可以包括:每次应用程序启动后存在未上报的内存状态信息;上一次上报的内存状态信息发送失败;服务器下发了内存状态信息上报许可。
其中,在上报内存状态信息时,可以将其压缩为压缩包,进而节约流量并提高上传效率;在上报成功后,可以将压缩包删除,节约用户的存储资源;若多次上报失败,可以直接将内存状态信息删除。
这里,终端设备上报内存状态信息后,服务器可以基于内存状态信息确定发生故障的内存状态节点,也即定位内存故障,还可以对发生内存故障的内存进行聚类,分析故障概率高的问题,详见服务器侧的描述。
本公开实施例提供的内存检测方法,能够获取目标应用程序对应的当前存活节点的属性信息,并根据属性信息确定内存节点的符号化信息和不同内存节点之间的引用关系信息,在将内存节点的属性信息、内存节点的符号化信息及引用关系信息作为内存状态信息,内存状态信息用于定位内存故障;也即,本公开实施例不需要记录内存分配的堆栈,也能获取到对内存节点进行问题分析定位的数据,可以避免因频繁记录内存分配的堆栈导致设备性能损耗过大的问题,有效节省内存检测所占用的计算资源;另外,基于反映内存节点用途的符号化信息和不同内存节点之间的引用关系信息,可以更全面地定位内存节点出现的问题。
参照图3所示,为本公开实施例提供的另一种内存检测方法,所述方法包括S301至S303,其中:
S301:获取终端设备上报的内存状态信息,所述内存状态信息包括目标应用程序对应的当前存活的内存节点的属性信息、符号化信息和引用关系信息;所述符号化信息用于表征所述内存节点的用途。
S302:基于所述内存节点的内存状态信息,确定发生异常的内存节点的异常信息。
该步骤中,在内存状态信息中包含符号化信息的情况下,可以基于所述内存节点的符号化信息、引用关系信息与所述属性信息,生成所述内存节点的引用图;基于所述内存节点的引用图,生成所述内存节点的支配树;基于所述内存节点的属性信息、引用图和支配树,确定发生异常的内存节点的异常信息。
示例性的,可以通过以下步骤生成支配树:
基于所述内存节点的引用图,确定从所述引用图中的根内存节点到达每个叶子内存节点必经的支配内存节点;
基于每个所述内存节点对应的支配内存节点,生成所述内存节点对应的支配树。
具体的,可以利用lengauer-tarjan算法生成支配树。
其中,内存节点的引用图中的节点代表内存节点,节点中可以包含该内存节点的属性信息以及符号化信息,引用图中的连接边代表不同内存节点之间的引用关系;支配树中的节点也代表内存节点,支配树中的连接边代表不同内存节点之间的支配关系,比如,若引用图中,从根节点到节点B必须经过节点A,则节点A支配节点B,在支配树上,若节点A为距离节点B最近的、支配节点B的节点,则节点A为节点B的父亲节点。
根据支配树的定义,如果节点A释放,节点A在支配树中的子树下的所有内存节点都应释放,所以我们可以通过支配树计算出节点A支配的内存的总大小,从而定位目标应用程序的内存主要是被那些节点所持有的,进而对目标应用程序进行内存分析。
参见图4及图5所示,分别为本公开实施例提供的内存检测方法中引用图的示意图以及支配树的示意图。图4中,引用图包含内存节点A、内存节点B、内存节点C、内存节点D、内存节点E以及内存节点F,其中,内存节点A为引用图的根节点,内存节点B引用内存节点A,内存节点C、内存节点D引用内存节点B,内存节点E、内存节点F引用内存节点C,内存节点E还引用内存节点D。图5中的支配树是基于图3中的引用图得到的,支配树中包含内存节点A、内存节点B、内存节点C、内存节点D内存节点E以及内存节点F,其中,内存节点A为根节点,内存节点A支配内存节点B,内存节点B支配内存节点C、内存节点D以及内存节点E,内存节点C支配内存节点F。
进一步的,根据引用图,可以确定内存节点是否发生内存泄漏,发生内存泄漏的内存节点会独立于引用图中的根节点,不被任何节点支配;通过支配树,可以判断哪个内存节点支配了过大的内存或过多的内存节点;通过内存节点的属性信息以及符号化信息,可以对具有相同符号化信息的内存节点分类,并确定每类内存节点的总占用内存的大小,并判断是否超出正常范围;通过携带有符号化信息的内存节点的数量,可以判断哪种内存节点的数量异常等。
S303:基于所述异常信息,针对发生异常的内存节点进行问题聚类,确定至少一种问题类型。
示例性的,可以基于所述异常信息和预设的至少一种异常维度,针对发生异常的内存节点进行每种异常维度下的问题聚类,确定每种异常维度对应的至少一种问题类型。
其中,聚类得到的任一种问题类型下的异常内存节点数量大于预设数量,和/或,聚类得到的任一种问题类型下的异常内存节点的占用内存之和大于预设占用内存阈值。
具体的,异常维度可以包括占用内存尺寸异常、内存节点发生内存泄漏以及自定义的异常。
其中,针对占用内存尺寸异常的异常维度,可以根据类名对内存节点进行分类,将类名(即符号化信息)相同的内存节点分为同一类,再计算每类内存节点的内存总占用量,并按照由高到低的顺序排序,并确定内存总占用量大于预设占用内存阈值的一类为问题类型;还可以根据每类内存节点的数量是否超过预设数量,若超过则确定该类为问题类型。
进一步的,针对内存节点发生内存泄漏的异常维度,可以将发生内存泄漏,并且类名相同的内存节点聚类在一起,进而通过聚类结果得知哪种内存节点存在何种异常。
一种可能的实施方式中,确定至少一种问题类型之后,该方法还包括:
基于确定的问题类型、每种问题类型关联的异常内存节点、所述引用图以及生成的所述支配树,生成所述内存状态信息对应的节点详情信息;
其中,所述节点详情信息中包含每个内存节点的问题聚类结果、内存状态信息、该内存节点在所述引用图中的引用信息以及该内存节点在所述支配树中的支配信息。
这里,可以基于问题类型、问题类型关联的异常内存节点、以及生成的支配树,生成内存状态信息中对应的节点详情信息,该节点详情信息中能够反映当前的内存状态信息中内存节点的问题聚类结果、内存状态信息以及内存节点在支配树中的支配信息;在检测到针对任一问题类型的详情查看操作后,可以,展示问题类型对应的节点详情信息,供业务人员进行内存节点的分析与判断,进而找到内存溢出的原因。
本公开实施例提供的内存检测方法,能够获取目标应用程序对应的内存节点的属性信息,并根据属性信息确定内存节点的符号化信息和不同内存节点之间的引用关系信息,在将内存节点的属性信息、内存节点的符号化信息及引用关系信息作为内存状态信息;也即,本公开实施例不需要记录内存分配的堆栈,也能获取到对内存节点进行问题分析定位的数据,可以避免因频繁记录内存分配的堆栈导致设备性能损耗过大的问题,有效节省内存检测所占用的计算资源;另外,基于反映内存节点用途的符号化信息和不同内存节点之间的引用关系信息,可以更全面地定位内存节点出现的问题。
本领域技术人员可以理解,在具体实施方式的上述方法中,各步骤的撰写顺序并不意味着严格的执行顺序而对实施过程构成任何限定,各步骤的具体执行顺序应当以其功能和可能的内在逻辑确定。
基于同一发明构思,本公开实施例中还提供了与内存检测方法对应的内存检测装置,由于本公开实施例中的装置解决问题的原理与本公开实施例上述内存检测方法相似,因此装置的实施可以参见方法的实施,重复之处不再赘述。
参照图6所示,为本公开实施例提供的一种内存检测装置的架构示意图,所述内存检测装置600包括:第一获取模块610、第二获取模块620、、信息确定模块630;其中,
第一获取模块610,用于获取目标应用程序对应的内存节点的属性信息;所述属性信息包括内存节点的内存尺寸和地址信息;
第二获取模块620,用于基于所述内存节点的属性信息,获取所述内存节点的符号化信息,以及内存节点之间的引用关系信息;所述符号化信息用于表征所述内存节点的用途;
信息确定模块630,将所述内存节点的属性信息、所述符号化信息、和所述引用关系信息作为内存状态信息;所述内存状态信息用于定位内存故障。
本公开实施例提供的内存检测装置,能够获取目标应用程序对应的内存节点的属性信息,并根据属性信息确定内存节点的符号化信息和不同内存节点之间的引用关系信息,在将内存节点的属性信息、内存节点的符号化信息及引用关系信息作为内存状态信息;也即,本公开实施例不需要记录内存分配的堆栈,也能获取到对内存节点进行问题分析定位的数据,可以避免因频繁记录内存分配的堆栈导致设备性能损耗过大的问题,有效节省内存检测所占用的计算资源;另外,基于反映内存节点用途的符号化信息和不同内存节点之间的引用关系信息,可以更全面地定位内存节点出现的问题。
一种可选的实施方式中,所述第一获取模块610在获取所述目标应用程序对应的内存节点的属性信息时,具体用于:
当检测到所述目标应用程序满足以下内存状态信息采集触发条件时,获取所述目标应用程序对应的内存节点的属性信息;其中,所述内存状态信息采集触发条件包括以下至少一项:
所述目标应用程序的占用内存大于预设的检测阈值;
在最近预设时间段内,没有触发过内存状态信息的采集;
在预设的时间周期内,采集内存状态信息的次数小于预设次数;
内存状态信息采集模块占用的存储空间大小小于设定阈值。
一种可选的实施方式中,所述第一获取模块610在检测目标应用程序是否满足预设的内存状态信息采集触发条件时,具体用于:
在检测到所述目标应用程序满足内存状态信息采集功能开启的前置条件后,周期性检测所述目标应用程序是否满足预设的内存状态信息采集触发条件;其中,所述前置条件包括以下至少一种:
所述目标应用程序的后台服务器下发了内存状态信息采集功能开启指令;运行所述目标应用程序的终端设备为真实设备;所述终端设备的系统版本高于设定版本;所述终端设备的配置信息满足预设配置条件。
一种可选的实施方式中,所述第一获取模块610在获取所述目标应用程序对应的当前存活的内存节点的属性信息时,具体用于:
获取所述目标应用程序对应的虚拟内存节点;和/或,获取目标应用程序对应的堆内存节点的属性信息。
一种可选的实施方式中,所述第二获取模块620在获取引用关系信息时具体用于:
将每个所述内存节点作为当前内存节点,基于所述当前内存节点的地址信息及内存尺寸,从所述当前内存节点的对应地址范围中查找指针格式数据值;
从除所述当前内存节点之外的每个内存节点的对应地址范围中,查找所述指针格式数据值,并根据查找结果确定所述当前内存节点对应的引用关系信息。
一种可选的实施方式中,所述第二获取模块620在从所述当前内存节点的对应地址范围中查找到至少一个指针格式数据值时,具体用于:
若所述当前内存节点为所述虚拟内存节点中的栈内存节点,则从所述栈内存节点已经使用的栈空间中确定栈指针所在的第一预设位置与栈基础指针所在的第二预设位置;
从所述第一预设位置与所述第二预设位置之间的地址范围内,查找指针格式数据值。
一种可选的实施方式中,所述第二获取模块620在根据搜索结果确定所述当前内存节点对应的引用关系信息之后,还用于:
若当前内存节点为Objective-C对象或Swift对象,则获取所述当前内存节点的运行信息;
若在所述运行信息中查找到目标实例对象,则将所述运行信息中所述目标实例变量的引用关系信息添加到确定的所述当前内存节点的引用关系信息中。
一种可选的实施方式中,若所述内存节点包括虚拟内存节点,所述虚拟内存节点的属性信息还包括用户标签,所述第二获取模块620在基于所述内存节点的属性信息,获取所述内存节点的符号化信息时,具体用于:
将所述虚拟内存节点对应的用户标签,作为所述虚拟内存节点的符号化信息;
和/或,
若所述内存节点包括堆内存节点,所述第二获取模块620,在基于所述内存节点的属性信息,获取所述内存节点的符号化信息时,用于:
基于所述内存节点的属性信息,按照预设的对象类型列表,获取所述堆内存节点在所述对象类型列表中任一对象类型下的符号化信息。
一种可选的实施方式中,所述第二获取模块620在按照预设的对象类型列表,获取所述堆内存节点在所述对象类型列表中任一对象类型下的符号化信息时,具体用于:
当所述对象类型包括Objective-C对象和/或Swift对象时,执行预设类名获取方法得到返回结果,获取所述返回结果指示的类的最小实例尺寸;基于所述最小实例尺寸以及所述堆内存节点的内存尺寸,确定所述堆内存节点的类名,并将确定的类名作为所述堆内存节点的所述符号化信息;
当所述对象类型包括C++对象时,在所述堆内存节点的对应地址范围内,获取所述C++对象对应的第一预设字段中的数据值,该数据值为目标虚函数表的指针;基于所述第一预设字段中的数据值,从预设的映射表中确定所述C++对象对应的目标虚函数表的类名,作为所述C++对象的符号化信息;所述映射表中包含多个虚函数表的指针与虚函数表对应的类名之间的映射关系;
当所述对象类型包括Core Foundation对象时,在所述堆内存节点的对应地址范围内,查找所述堆内存节点的类名的索引标识;基于所述索引标识执行Core Foundation对象对应的预设查询方法,获取所述堆内存节点的类名,作为所述堆内存节点的所述符号化信息。
一种可能的实施方式中,所述第二获取模块620还用于通过以下步骤生成所述映射表:
从所述目标应用程序对应的内存中的第二预设字段中,搜索出至少一个虚函数表的类名;
基于所述搜索到的虚函数表的类名,从所述目标应用程序对应的内存中的第三预设字段中,搜索出所述虚函数表,并获取搜索到的虚函数表的指针;
建立搜索得到的虚函数表的类名与所述虚函数表的指针之间的映射关系,得到所述映射表。
一种可选的实施方式中,所述信息确定模块630在将所述内存状态信息上报给服务器之前,还用于:
利用所述目标应用程序的操作系统中的预设写入接口,将所述内存状态信息写入到所述操作系统对应的终端设备的磁盘中。
一种可选的实施方式中,所述第二获取模块620在从除当前内存节点之外的每个内存节点的对应地址范围中搜索所述数据值时,具体用于:
采用二分法从除当前内存节点之外的每个虚拟内存节点的对应地址范围中搜索所述数据值;
若未在虚拟内存节点对应地址范围中搜索到所述数据值,则采用哈希法从除当前内存节点之外的每个堆节点的对应地址范围中搜索所述数据值。
一种可选的实施方式中,所述信息确定模块630在将所述内存节点的属性信息、所述符号化信息、和所述引用关系信息作为内存状态信息上报给服务器时,具体用于:
在根据所述目标应用程序的后台服务器下发的上报策略,确定当前满足所述上报策略指示的上报触发条件时,将所述内存状态信息上报给服务器。
参照图7所示,为本公开实施例提供的一种内存检测装置的架构示意图,所述内存检测装置700包括:第三获取模块710、第一确定模块720、第二确定模块730;其中,
第三获取模块710,用于获取终端设备上报的内存状态信息,所述内存状态信息包括目标应用程序对应的当前存活的内存节点的属性信息、符号化信息和引用关系信息;所述符号化信息用于表征所述内存节点的用途;
第一确定模块720,用于基于所述内存节点的内存状态信息,确定发生异常的内存节点的异常信息;
第二确定模块730,用于基于所述异常信息,针对发生异常的内存节点进行问题聚类,确定至少一种问题类型。
一种可选的实施方式中,所述内存状态信息还包括所述内存节点的符号化信息;
所述第一确定模块720具体用于:
基于所述内存节点的符号化信息、引用关系信息与所述属性信息,生成所述内存节点的引用图;
基于所述内存节点的引用图,生成所述内存节点的支配树;
基于所述内存节点的属性信息、引用图和支配树,确定发生异常的内存节点的异常信息。
一种可选的实施方式中,所述第一确定模块720在基于所述内存节点的引用图,生成所述内存节点的支配树时,具体用于:
基于所述内存节点的引用图,确定从所述引用图中的根内存节点到达每个叶子内存节点必经的支配内存节点;
基于每个所述内存节点对应的支配内存节点,生成所述内存节点对应的支配树。
一种可选的实施方式中,所述第二确定模块730具体用于:
基于所述异常信息和预设的至少一种异常维度,针对发生异常的内存节点进行每种异常维度下的问题聚类,确定每种异常维度对应的至少一种问题类型;
其中,聚类得到的任一种问题类型下的异常内存节点数量大于预设数量,和/或,聚类得到的任一种问题类型下的异常内存节点的占用内存之和大于预设占用内存阈值。
一种可选的实施方式中,所述第二确定模块730在确定至少一种问题类型后,还用于:
基于确定的问题类型、每种问题类型关联的异常内存节点、所述引用图以及生成的所述支配树,生成所述内存状态信息对应的节点详情信息;
其中,所述节点详情信息中包含每个内存节点的问题聚类结果、内存状态信息、该内存节点在所述引用图中的引用信息以及该内存节点在所述支配树中的支配信息。
关于装置中的各模块的处理流程、以及各模块之间的交互流程的描述可以参照上述方法实施例中的相关说明,这里不再详述。
基于同一技术构思,本公开实施例还提供了一种计算机设备。参照图8所示,为本公开实施例提供的计算机设备800的结构示意图,包括处理器801、存储器802、和总线803。其中,存储器802用于存储执行指令,包括内存8021和外部存储器8022;这里的内存8021也称内存储器,用于暂时存放处理器801中的运算数据,以及与硬盘等外部存储器8022交换的数据,处理器801通过内存8021与外部存储器8022进行数据交换,当计算机设备800运行时,处理器801与存储器802之间通过总线803通信,使得处理器801在执行以下指令:
获取目标应用程序对应的内存节点的属性信息;所述属性信息包括内存节点的内存尺寸和地址信息;
基于所述内存节点的属性信息,获取所述内存节点的符号化信息,以及内存节点之间的引用关系信息;所述符号化信息用于表征所述内存节点的用途;
将所述内存节点的属性信息、所述符号化信息、和所述引用关系信息作为内存状态信息;所述内存状态信息用于定位内存故障。
一种可能的实施方式中,处理器801执行的指令中,获取所述目标应用程序对应的内存节点的属性信息,包括:
在检测到所述目标应用程序满足以下内存状态信息采集触发条件后,获取所述目标应用程序对应的内存节点的属性信息;其中,所述内存状态信息采集触发条件包括以下至少一项:
所述目标应用程序的占用内存大于预设的检测阈值;
在最近预设时间段内,没有触发过内存状态信息的采集;
在预设的时间周期内,采集内存状态信息的次数小于预设次数;
内存状态信息采集模块占用的存储空间大小小于设定阈值。
一种可能的实施方式中,处理器801执行的指令中,检测目标应用程序是否满足预设的内存状态信息采集触发条件,包括:
在检测到所述目标应用程序满足内存状态信息采集功能开启的前置条件后,周期性检测所述目标应用程序是否满足预设的内存状态信息采集触发条件;其中,所述前置条件包括以下至少一种:
所述目标应用程序的后台服务器下发了内存状态信息采集功能开启指令;运行所述目标应用程序的终端设备为真实设备;所述终端设备的系统版本高于设定版本;所述终端设备的配置信息满足预设配置条件。
一种可能的实施方式中,处理器801执行的指令中,所述获取所述目标应用程序对应的内存节点的属性信息,包括:
获取所述目标应用程序对应的虚拟内存节点和/或堆内存节点的属性信息。
一种可能的实施方式中,处理器801执行的指令中,所述基于所述内存节点的属性信息,获取内存节点之间的引用关系信息,包括:
将每个所述内存节点作为当前内存节点,基于所述当前内存节点的地址信息及内存尺寸,从所述当前内存节点的对应地址范围中查找指针格式数据值;
从除所述当前内存节点之外的每个内存节点的对应地址范围中,查找所述指针格式数据值,并根据查找结果确定所述当前内存节点对应的引用关系信息。
一种可能的实施方式中,处理器801执行的指令中,所述从所述当前内存节点的对应地址范围中查找到至少一个指针格式数据值,包括:
若所述当前内存节点为所述虚拟内存节点中的栈内存节点,则从所述栈内存节点已经使用的栈空间中确定栈指针所在的第一预设位置与栈基础指针所在的第二预设位置;
从所述第一预设位置与所述第二预设位置之间的地址范围内,查找指针格式数据值。
一种可能的实施方式中,处理器801执行的指令中,根据搜索结果确定所述当前内存节点对应的引用关系信息之后,还包括:
若当前内存节点为Objective-C对象或Swift对象,则获取所述当前内存节点的运行信息;
若在所述运行信息中查找到目标实例对象,则将所述运行信息中所述目标实例变量的引用关系信息添加到确定的所述当前内存节点的引用关系信息中。
一种可能的实施方式中,处理器801执行的指令中,若所述内存节点包括虚拟内存节点,所述虚拟内存节点的属性信息还包括用户标签,所述基于所述内存节点的属性信息,获取所述内存节点的符号化信息,包括:
根据所述用户标签,确定所述虚拟内存节点的符号化信息;
和/或,
若所述内存节点包括堆内存节点,所述基于所述内存节点的属性信息,获取所述内存节点的符号化信息,包括:
基于所述内存节点的属性信息,依次获取所述堆内存节点在预设的多个对象类型下的符号化信息。
一种可能的实施方式中,处理器801执行的指令中,所述依次尝试获取所述堆内存节点在不同对象类型下的符号化信息,包括:
在所述对象类型包括Objective-C对象和/或Swift对象的情况下,执行所述Objective-C对象和/或Swift对象对应的预设类名获取方法;若执行所述类名获取方法后的返回结果非空,利用预设的实例大小获取接口获取所述返回结果指示的类的最小实例大小;基于所述最小实例大小,以及所述堆内存节点的大小,确定所述堆内存节点的类名,并将确定的类名作为所述堆内存节点的所述符号化信息;
在所述对象类型包括C++对象的情况下,在所述堆内存节点的对应地址范围内,获取所述C++对象对应的第一预设字段中的数据值;基于所述第一预设字段中的数据值,以及预先生成的映射表,确定所述C++对象对应的目标虚函数表的类名;所述映射表中包含多个虚函数表的指针与虚函数表对应的类名之间的映射关系;将所述目标虚函数表的类名作为所述C++对象的符号化信息;
在所述对象类型包括Core Foundation对象的情况下,在所述堆内存节点的对应地址范围内,查找所述堆内存节点的类名的索引标识;若所述索引标识处于预设的有效参数值范围内,则利用Core Foundation对象对应的预设查询方法,获取所述堆内存节点的类名,并将获取的类名作为所述堆内存节点的所述符号化信息。
一种可能的实施方式中,处理器801还用于执行:
从所述目标应用程序对应的内存中的第二预设字段中,搜索出至少一个虚函数表的类名;
基于所述搜索到的虚函数表的类名,从所述目标应用程序对应的内存中的第三预设字段中,搜索出所述虚函数表,并获取搜索到的虚函数表的指针;
建立搜索得到的虚函数表的类名与所述虚函数表的指针之间的映射关系,得到所述映射表。
一种可能的实施方式中,处理器801执行的指令中,在将所述内存状态信息上报给服务器之前,所述方法还包括:
利用所述目标应用程序的操作系统中的预设写入接口,将所述内存状态信息写入到所述操作系统对应的终端设备的磁盘中。
一种可能的实施方式中,处理器801执行的指令中,所述从除当前内存节点之外的每个内存节点的对应地址范围中搜索所述数据值,包括:
采用二分法从除当前内存节点之外的每个虚拟内存节点的对应地址范围中搜索所述数据值;
若未在虚拟内存节点对应地址范围中搜索到所述数据值,则采用哈希法从除当前内存节点之外的每个堆节点的对应地址范围中搜索所述数据值。
一种可能的实施方式中,处理器801执行的指令中,将所述内存节点的属性信息、所述符号化信息、和所述引用关系信息作为内存状态信息上报给服务器,包括:
在根据所述目标应用程序的后台服务器下发的上报策略,确定当前满足所述上报策略指示的上报触发条件时,将所述内存状态信息上报给服务器。
基于同一技术构思,本公开实施例还提供了另一种计算机设备。参照图9所示,为本公开实施例提供的计算机设备900的结构示意图,包括处理器901、存储器902、和总线903。其中,存储器902用于存储执行指令,包括内存9021和外部存储器9022;这里的内存9021也称内存储器,用于暂时存放处理器901中的运算数据,以及与硬盘等外部存储器9022交换的数据,处理器901通过内存9021与外部存储器9022进行数据交换,当计算机设备900运行时,处理器901与存储器902之间通过总线903通信,使得处理器901在执行以下指令:
获取终端设备上报的内存状态信息,所述内存状态信息包括目标应用程序对应的当前存活的内存节点的属性信息、符号化信息和引用关系信息;所述符号化信息用于表征所述内存节点的用途;
基于所述内存节点的内存状态信息,确定发生异常的内存节点的异常信息;
基于所述异常信息,针对发生异常的内存节点进行问题聚类,确定至少一种问题类型。
一种可选的实施方式中,处理器901执行的指令中,所述基于所述内存节点的内存状态信息,确定发生异常的内存节点的异常信息,包括:
基于所述内存节点的符号化信息、引用关系信息与所述属性信息,生成所述内存节点的引用图;
基于所述内存节点的引用图,生成所述内存节点的支配树;
基于所述内存节点的属性信息、引用图和支配树,确定发生异常的内存节点的异常信息。
一种可选的实施方式中,处理器901执行的指令中,所述基于所述内存节点的引用图,生成所述内存节点的支配树,包括:
基于所述内存节点的引用图,确定从所述引用图中的根内存节点到达每个叶子内存节点必经的支配内存节点;
基于每个所述内存节点对应的支配内存节点,生成所述内存节点对应的支配树。
一种可选的实施方式中,处理器901执行的指令中,所述基于所述异常信息,针对发生异常的内存节点进行问题聚类,确定至少一种问题类型,包括:
基于所述异常信息和预设的至少一种异常维度,针对发生异常的内存节点进行每种异常维度下的问题聚类,确定每种异常维度对应的至少一种问题类型;
其中,聚类得到的任一种问题类型下的异常内存节点数量大于预设数量,和/或,聚类得到的任一种问题类型下的异常内存节点的占用内存之和大于预设占用内存阈值。
一种可选的实施方式中,处理器901执行的指令中,确定至少一种问题类型之后,还包括:
基于确定的问题类型、每种问题类型关联的异常内存节点、所述引用图以及生成的所述支配树,生成所述内存状态信息对应的节点详情信息;
其中,所述节点详情信息中包含每个内存节点的问题聚类结果、内存状态信息、该内存节点在所述引用图中的引用信息以及该内存节点在所述支配树中的支配信息。
本公开实施例还提供一种计算机可读存储介质,该计算机可读存储介质上存储有计算机程序,该计算机程序被处理器运行时执行上述方法实施例中所述的内存检测方法的步骤。其中,该存储介质可以是易失性或非易失的计算机可读取存储介质。
本公开实施例所提供的内存检测方法的计算机程序产品,包括存储了程序代码的计算机可读存储介质,所述程序代码包括的指令可用于执行上述方法实施例中所述的内存检测方法的步骤,具体可参见上述方法实施例,在此不再赘述。
本公开实施例还提供一种计算机程序,该计算机程序被处理器执行时实现前述实施例的任意一种方法。该计算机程序产品可以具体通过硬件、软件或其结合的方式实现。在一个可选实施例中,所述计算机程序产品具体体现为计算机存储介质,在另一个可选实施例中,计算机程序产品具体体现为软件产品,例如软件开发包(Software DevelopmentKit,SDK)等等。
所属领域的技术人员可以清楚地了解到,为描述的方便和简洁,上述描述的系统和装置的具体工作过程,可以参考前述方法实施例中的对应过程,在此不再赘述。在本公开所提供的几个实施例中,应该理解到,所揭露的系统、装置和方法,可以通过其它的方式实现。以上所描述的装置实施例仅仅是示意性的,例如,所述单元的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,又例如,多个单元或组件可以结合或者可以集成到另一个系统,或一些特征可以忽略,或不执行。另一点,所显示或讨论的相互之间的耦合或直接耦合或通信连接可以是通过一些通信接口,装置或单元的间接耦合或通信连接,可以是电性,机械或其它的形式。
所述作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部单元来实现本实施例方案的目的。
另外,在本公开各个实施例中的各功能单元可以集成在一个处理单元中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个单元中。
所述功能如果以软件功能单元的形式实现并作为独立的产品销售或使用时,可以存储在一个处理器可执行的非易失的计算机可读取存储介质中。基于这样的理解,本公开的技术方案本质上或者说对现有技术做出贡献的部分或者该技术方案的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行本公开各个实施例所述方法的全部或部分步骤。而前述的存储介质包括:U盘、移动硬盘、只读存储器(Read-OnlyMemory,ROM)、随机存取存储器(Random Access Memory,RAM)、磁碟或者光盘等各种可以存储程序代码的介质。
最后应说明的是:以上所述实施例,仅为本公开的具体实施方式,用以说明本公开的技术方案,而非对其限制,本公开的保护范围并不局限于此,尽管参照前述实施例对本公开进行了详细的说明,本领域的普通技术人员应当理解:任何熟悉本技术领域的技术人员在本公开揭露的技术范围内,其依然可以对前述实施例所记载的技术方案进行修改或可轻易想到变化,或者对其中部分技术特征进行等同替换;而这些修改、变化或者替换,并不使相应技术方案的本质脱离本公开实施例技术方案的精神和范围,都应涵盖在本公开的保护范围之内。因此,本公开的保护范围应所述以权利要求的保护范围为准。