用于内存泄漏诊断的方法和装置的利记博彩app

文档序号:6465621阅读:255来源:国知局
专利名称:用于内存泄漏诊断的方法和装置的利记博彩app
技术领域
本发明涉及一种用于垃圾收集语言的内存泄漏诊断的方法和装置。
背景技术
在一些编程语言以及相关的运行时间(runtime)中,通常会由应用程序 本身提供一种内存管理功能。对于那不再被程序需要的内存是由程序设计员 来释放。如果程序不能合理释放不同的内存将导致内存资源的浪费,即这些 内存将不能被任何其他的程序使用。导致这种内存浪费的程序错误通常称之 为"内存泄漏"。在有些编程语言中,会采用自动内存管理而不是依赖程序员 释放内存。这种自动内存管理在本领域通常称之为"垃圾收集",就是一种与 编程语言以及其相关的运行时间的实施相关的运行时间系统的主动元件。这
员部分地从释放内存的管理工作中解脱出来。但是,自动内存管理会产生另 一个问题,就是有些对象保留对部分内存中的数据结构的引用(reference),
动垃圾收集器回收那些不再被使用的内存部分,也导致了 "内存泄漏"。因 此,尽管垃圾收集机制帮助减少了 "内存泄漏"问题,但是后一种内存泄漏 仍旧存在并导致计算机的性能降低,严重的时候会导致应用程序的运行占用 所有的内存并导致计算机崩溃。因此,内存泄漏由于其对计算机的性能造成 巨大影响而削弱了计算机的可获得性和安全性。
对于支持自动内存管理的运行时间中的内存泄漏,其主要以两类方式存 在 一类是通过每次执行而快速地创建大量的泄漏或以至于为人所觉察的方 式创建泄漏;另一类是通过每次执行而连续微妙地以至于无法察觉地创建泄 漏。
如何发现和找到那些正在泄漏的对象以及快速找到泄漏的原因是本领域 需要解决的问题。 一个系统的泄漏诊断起来是非常复杂的,尤其是对于那些 每次连续以及较小容量地发生的緩慢泄漏而言是如此。对于在堆上的不明显
5的增长是非常难以辨识的。通常,在发现泄漏时已经为时已晚,泄漏程序已 经对整个系统造成了严重的影响。这对于那种开始很小但是在整个运行时间 段内持续增长的泄漏而言尤其如此。有时,在问题大到足以可注意之前需要 高达几周的服务时间。识别这些潜在泄漏是非常困难的,尤其是对于不能忍
受多次堆(heap )访问甚至堆转储(dump )的在线系统(live productive system ) 而言是如此,因为这些系统不能忍受由于堆操作需要的执行暂停。尽管现在 存在各种垃圾回收方式并且也各有益处,但是这种内存泄漏对于Java程序而 言依然是一个问题。
目前,现有的一些技术有助于用户对黑箱进行研究以便确定在运行时间 (runtime)处的根本原因。对诊断内存泄漏,现有技术主要依赖于比较区分 堆快照(snapshot)(堆快照是一种由像节点一样的类型以及其间的引用构成 的图(graph))以及根据对象数量的增长来进行诊断。这些技术在每轮垃圾 收集之后监视堆,并且观察自由空间的向下的锯齿图形(内存的使用率曲线 图)直到程序无法在从堆上获得空间为止(每次收集的、可供以后使用的内 存越来越少)。这种现有的技术并不能用于在线系统,因为这种堆快照的获取 和分析会使得具有较大的堆容量的系统暂停几十秒。对于诸如服务器的在线 系统而言,这种延迟或暂停会导致超时,从而显著影响在线应用的表现。基 于上述原因,这种延迟和暂停对于在线系统而言是完全不可接受的。
而且,用于大型应用程序的内存堆往往容量巨大,因此,试图对堆快照 进行频繁的比较对这些应用程序的诊断帮助有限,因为泄漏对象并不明显, 但是如果利用现有技术进行泄漏诊断,应用程序会由于为进行泄漏诊断而频 繁进行堆快照的比较操作而减慢,这将对服务质量以及用户的体验带来负面
到很大干扰(perturb)以至于不具有实际价值,尤其是在在线环境下。
现有的内存泄漏的诊断方法对工业应用的效果有限,因为这些现有的方 法通常将基本类型识别为嫌疑类型。例如, 一种现有技术建议使用引用 (reference)来查找负责内存泄漏的有用对象。但是引用不能包含执行语境 信息。被引用的嫌疑对象因为是基本的常见使用类型,可能同时被多个引用 者持有。在这种情况下,人们依然不了解这些引用为什么会产生以及在何种 条件下泄漏问题会被再现。诊断以及修复是否正确难以进行判别。
在目前的实践中, 一方面,依赖多次取得全引用图快照并对其进行引用分析对于大规模在线系统而言成本过于昂贵。另一方面,在发明人的经验中, 为了诊断内存泄漏,用户必须寻找可能具有问题的候选数据结构。但是,发 现将要关注的正好的数据结构非常困难。当探寻服务(尤其是大型在线系统) 的引用图时,噪声、复杂性以及规模问题会使得引用图的分析非常困难。当 在长时间运行的系统中诊断缓慢的内存泄漏时,噪声可能是一个特别的问题。 噪声影响可能会矮化诊断緩慢泄漏所需的证据直到其运行了很久之后为止。
概括而言,现有技术方案主要集中在以下几点反复访问堆甚至进行堆
转储来产生堆快照、在不同的快照之间进行比较以便找到作为泄漏候选的增 长节点、找到嫌疑结构、以及分析引用图从而找到造成内存被不当持有的引 用者以便随后进行确认。因此,目前针对内存泄漏路径所采取的方法通常包
括两个步骤诊断并确认诊断以及修复泄漏点。但是在诊断和确认诊断之间 存在断层(gap),现有技术在内存泄漏诊断方面所能提供的帮助有限。 根据以上描述可知,现有的内存泄漏诊断技术存在以下技术问题
1. 效率低下。现有的途径需要用户手动将这些高速緩存对象与真正的泄 漏对象区分开。总体而言,这些途径使得用户忙于应付关于所创建的各个对 象的众多低水平的细节,普通用户很难解释复杂引用图以获得相关问题执行 环境。这些解释处理需要大量的专门知识。即使对于专家而言,这也通常需 要进行很长时间的分析工作来发现泄漏的根本原因。
2. 堆访问会对所运行的系统造成的干扰(perturbation )。这些技术在有 些情况下将使得运行的系统不稳定以至于不具有实际价值,尤其是在在线境 下。获取引用图后需要对堆快照执行比较分析,这些工作甚至可以造成具有 较大堆尺寸的系统暂停几十秒。如前所述,对于服务器而言,这些延迟或暂 停会导致超时(timeout),并且显著地改变系统的特性。
3. 基于堆增长进行泄漏分析受到限制。现有的一些工具利用堆的增长和 对堆进行区分来发现内存泄漏,以便发现使得堆增长的对象。尽管堆增长是 有助于判别的有用的参数,但是仅仅使用增长作为一种启发来发现泄漏依然 存在许多问题。毕竟,增长的对象或类型并不一定就是泄漏并且泄漏也并不 一定就会增长。
4. 基于引用进行的泄漏分析受到限制。仅仅知晓占支配地位的泄漏对象 的类型,通常是诸如"串型"的低级类型,对解释为什么会发生内存泄漏的 帮助有限,这是因为这些串可能被用于多个语境中,甚至可能在相同的数据结构(例如DOM文件)中被用于多种用途。此外由于一个低级泄漏对象可 能同时被多个引用者不当持有,因此很容易在分析引用图、提取泄漏的原因
时导致迷失。单一的DOM对象包含有成千上万个对象,并且在其间存在丰 富的引用网络。如果对架构的实施不了解,就很难获知要遵循引用路径中的 那个路径、获知何时分析分配调用路径、或者哪个调用位置是重要的。
5.基于类型分配堆栈进行的泄漏分析受到限制。有些方法能够通过监视 堆而同时记录每一个类型对象的分配堆栈,但并不是嫌疑类型的所有实例正 在泄漏,因此实际泄漏路径趋向被淹没在所有堆栈之间,并且存储和分析这 些堆栈需要付出运行时间和运行空间的代价。通常,泄漏位置不是与分配位 置映射,而是与分配函数的调用者相映射。例如,Java数据库连接(JDBC) 通过由一个类调用的一个代理类被反复地创建,所述调用的类会忘记调用该 代理类的JDBC释放函数。这样,就必须对调用者进行分析。
综上可见,现有技术现需要进行复杂图分析以及丰富的程序知识,为泄 漏的确认以及修复提供有限的线索。
本申请的目的在于解决现有技术中存在的上述技术问题。

发明内容
发明人注意到,现有的方法主要集中在内存泄漏的查找,但是很少关注 与泄漏问题直接相关的分配路径的认识。辨识其上可能发生泄漏的分配路径 能够直接获得与泄漏分析相关的信息,指引用户跟踪嫌疑对象分配和使用。
基于以上认识以及为了避免上述现有技术的缺点,本发明提供了 一种能 够用于活动系统的内存泄漏诊断装置和方法。
根据本发明的一个方面,提供了一种用于诊断内存泄露的方法,包括 跟踪应用程序在虛拟机上运行过程中的对象分配,从而获取并记录对象的分 配路径和分配时间;以预定的时间间隔计算每一类对象在其分配路径的年龄 代数;以及将其上具有高年龄代数对象的分配路径确定为可能存在内存泄漏 的分配路径,并报告给用户以进行分析。
根据本发明的另一个方面,提供了一种诊断内存泄漏的装置,包括
对象分配跟踪器件,跟踪应用程序在虚拟机上运行过程中的对象分配, 从而获取并记录对象的分配路径和分配时间;分配路径记录器件,用于记录 从对象分配跟踪器件传送来的每个对象的分配路径和分配时间;用于应用程
8序的堆,用于存储从分配路径记录器件传送来的路径分配的对象信息;分配
路径读取器件,用于读取所述堆中路径分配的对象信息,并扫描存储器中存
储的每个对象的id以及对应的分配路径信息,以便针对每条分配路径整理由 它分配的、并且还没有被回收的对象并根据每个对象的分配时间计算该路径 所分配同一类对象的年龄代数;分配路径排序器件,用于根据每条路径分配 的、并且存活的对象的年龄代数把路径排序;以及诊断报告器件,用于对从 分配路径排序器传送来的分配路径的排序数据进行分析,并将高排序的分配 路径确定为可能存在内存泄漏的分配路径报告给用户以进行分析。
根据本发明的另一个方面,还提供一种用于诊断内存泄漏的装置,包括 对象分配跟踪器件,用于跟踪应用程序在虚拟机上运行过程中的对象分 配,从而获取对象的分配路径和分配时间;分配路径记录器件,用于在每个 所分配的对象上打上包含其分配路径与分配对象的对应关系的标签;用于应 用程序的堆,用于存储从分配路径记录器件传送来的路径分配的对象信息; 分配路径读取器件,对每条分配路径直接按照标签从所述堆中读取由它分配 的、并且还没有被回收的对象,并根据每个对象的分配时间计算该路径所分 配同一类对象的年龄代数;分配路径排序器件,用于根据每条路径分配的、
并且存活的对象的年龄代数把路径排序;以及诊断报告器件,用于对从分配 路径排序器传送来的分配路径的排序数据进行分析,并将高排序的分配路径 确定为可能存在内存泄漏的分配路径报告给用户进行分析。


下面参照附图仅作为示例详细描述本发明的实施例,其中
图1表示在执行应用程序的过程中用于管理所分配对象的信息的数据结
构;
图2所示的是本发明所使用的标签的结构的示意图。; 图3所示的是在不同波段上的同类对象之间的调用关系的示意图; 图4所示的是提取每个对象的分配路径以及将所述分配路径与具体对象 进行绑定的过程示意图5所示的是不同位置层级的结构以及进行对象聚合的示意图。 图6所示的是诊断一个应用程序所造成的内存泄漏的流程图 图7所示的是用于诊断内存泄漏的装置的一个实施例。图8所示的是用于诊断内存泄漏的装置的另 一个实施例。
具体实施例方式
现在将参考本发明的示例性实施例进行详细的描述,在附图中图解说明 了所述实施例的示例,其中相同的参考数字始终指示相同的元件。应当理解, 本发明并不限于所公开的示例实施例。还应当理解,并非所述方法和设备的 每个特征对于实施任一权利要求所要求保护的本发明都是必要的。此外,在
整个公开中,当显示或描述处理或方法时,方法的步骤可以以任何顺序或者 同时执行,除非从上下文中能清楚一个步骤依赖于先执行的另一步骤。此外, 步骤之间可以有显著的时间间隔。
申请人发现,泄漏的对象通常属于一种类型,并且该类型的实例在不同 的间隔期间被连续地生成、分配。考虑到这种情形,在本发明的方法中,首 先辨识与这种分配一致的类的类型。随后,找到创建该类型的实例的路径。 本发明关注在每一个相对较长的间隔中连续创建的同一类对象。为了实现本 发明的目的,本发明提出了一种数据结构对同一类型的对象分配进行跟踪, 如图1所示。每种面向对象的应用程序都包含有不同类型的对象。针对每种 类型的对象,都构建一种便于记录其分配路径的列表。这种数据结构中包含 了类的签名、对象计数、时间计数器以及分配路径(一个对象的分配路径是 其分配时刻的堆栈映象)。通过这种数据结构对对象的分配进行管理。
参见图1,针对同一种类型的对象,在应用程序的过程中可能在不同的 路径上被分配。因此根据图l所示的数据结构,针对每条分配路径进行跟踪, 利用计数器记录在该路径上分配的对象数量,当分配数量超过一定规模的时 候在计时器中记录相应的时刻。换句话说,计时器中记录了分配数量连续到 达制定规模的时间间隔长度。。对所述的对象的分配信息的跟踪,可以通过后
面将结合图6和7所详细描述的对象分配跟踪器件61来进行。对于所跟踪获 得这种对象的信息,可以由将结合图6和7所详细描述的分配路径记录器件 62记录起来并存储到相应的存储器63中或直接发送到应用程序的堆中。
对于所记录的具有上述数据结构的对象信息,可以采用专门的分配路径 管理器件来进行管理,也可以在直接将相关的对象信息发送到堆之前对每个 所分配的对象打上独特的标签,以便将每个对象(即使是相同类的对象)区 分开来。图2所示的就是本发明可以使用的这种标签的形式。针对每个所分配的对象的一个标签包^"了多个字^殳。就本发明所示的图2中的实施例而言,
所述标签结构中的第一字段是该对象的标识符字段id,其表示了该对象属于 哪个波段(band)以及那个组(group),俩者的组合唯一的标志了该对象所 处的"年龄代数",其中对象的年龄是指从其被分配一直到被释放的时间,其 年龄代数可以用该对象自分配起直到被回收所经历的"垃圾回收,,次数或者 该对象存在时间相对于某一预定时间阈值的倍数。在这里,默认每一次垃圾 回收都会检索所有在堆中分配内存的对象。第二字段表示类字段,表示该对 象属于那个类,例如图l中所示的类l、类2、类3......等。第三字段属于路
径字段,表述该对象位于图1中所示的哪个路径上。第四字段是方法字段, 该方法字段并不是一种方法签名的真实内容,而是一个地址,指向方法签名 的实际存贮。最后一个字段是被调用者字段,被用来寻找分配的路径。该字 段与第四个字段结合,可以恢复出分配指定对象的路径内容。图3就表示出 了如何基于不同年龄代数的对象标签,从调用关系字段和方法字段恢复出基 本的路径信息。
下面,本发明将参照图4对本发明如何跟踪对象分配以及分配路径以及 如何在分配过程中计数进行详细的描述。
图4所示的是提取每个对象的分配路径以及将所述分配路径与具体对象 进行绑定标签的过程示意图。在应用程序运行时,对象的分配被跟踪。对于 类型i的对象,当该对象的总数达到阄值H时记录时间Ti,同时将该计数器 值重置为0。当该对象的总数再次达到阈值H时记录时间Ti+1。如果Ti和Tj+, 之间的差值超过阈值Tt时,该类型i就被识别需要进行下一阶段的跟踪记录 过程,如果类型i进入下一阶段的记录过程,分配i对象的路径将被记录下来 以及在该路径上分配i类型对象的总数也被记录。对于由路径Pi所分配的类 型i的对象,在Pi上的当前层级(tier,层级代表分配研究对象的堆栈位置, 因为堆栈是分层结构的,所以使用层级来标志堆栈中的位置),在本发明中也 称之为波段(band),的位置被标签到对象上。如果Tj和Tw之间的差值小于 阈值Tt时,类型i的计数不变,随着新实例的分配而增加。当对象的总数在 时间Ti+I处再次达到阈值H时其数量并且Tj和Tj+,之间的差值超过阁值Tt 时,该数量被重置为0,并且采用Tjw的值替代Tj,并且增加Pi上的层级, 以便后面分配的对象将采用下一等级的位置来标签。如此对Pi上的的每个等 级的位置逐步地执行相同的处理和判断,以便这些等级将被标签在对象上。阈值Tt选择对于在服务期间辨识寿命(lifetime)分布是非常有帮助的。 该默认值被设定为平均GC (垃圾收集)间隔。Nt的选择被用于安排对象分配 的规模或度量(scale ),这有助于发现用于相对频繁地分配一种类型对象的路 径。这种相对频繁地分配一种类型的对象的分配路径很可能与持续泄漏相关。 当属于 一种类型的对象被分配的总数超过阈值Nt时,这种类型的对象被辨识 出来并且其分配路径必须予以重视。当在固定路径中分配的对象的数量超过 阈值Nt时,该路径被辨识出来并通过将其自身与所创建的实例绑定起来而被 记录。如果达到伐值的时间太短(<Tt),绑定到对象上的标签不变。如果时 间足够长(>=1\),新的标签将被给予被分配的对象。这种绑定间隔导致标记 不同频带id和组id的组合的对象之间的分配时间至少长于Tt。换句话说,组 id和频带id的组合唯一的标记了不同年龄代数的对象。这种标记方式直接有 助于在堆访问的同时进行泄漏诊断,并输出泄漏对象以及直接相关的泄漏路径。
为了区分不同位置的层级(一个位置的层级表示其位于整个分配路径上
例如,频带O被赋予位于分配路径的顶部的分配位置,该位置直接创建对象, 而频带1则赋予调用频带0的位置的分配位置。这样对诊断泄漏对象以及跟 踪对象标签的分配路径非常有用,该对象标签将在下面两部分中引入。组id 被引入以防频带的值满溢当频带代表的层级数超过分配路径的最大深度时, 组id从0开始自增。频带值每满溢一次,组id自增l。组id和频带id的组 合对于后面的诊断非常重要。图5所示的就是这种层级的示意图。
下面所示的程序代码表示出了本发明是如何基于图1中所示的结构来跟 踪管理对象的分配的,也是对上面的具体描述的一种程序表示。该程序代码 在Java对象-陂分配时^f皮调用。
New—object ()
/*Get class signature of the object's class.*/ classSignature = GetClassSignature ()
/*Find the class index inhashTable, if it's not exist, putitintohashTable.*/ class工ndex = getAndPutClass ( classSignature ) /★Increase the object count of this class.*/ countClass (),'
/*If count of this class > Nt, count this ojbect to it's allocation path.*/ if( objectCount 〉 Mt ){ /*Find allocation path in this class structure, if it's not exist, put it into hashTsble.*/
getAndPutAllocationPath(); /*Tag this object with allocation path's band, class index, method of theband and its callee.V
tagObject(allocPathBand, class工ndex, methodOfBand, callee)/ "Increase the object count of this allocation path of this class ,*/ countAllocPath (),-
/*If the allocation path count 〉 Nt and time since last change of allocation path's band larger than Tt,then increase band of the allocation path, and reset its count, and update lastChangeTime*/
if( countOfAllocPath 〉 Nt && time—interval 〉 Tt ) moveToNextBand ()
}}
以上对对象的分配的跟踪和记录进行详细的描述。这种对各种类型的对 象的分配的跟踪和记录是为了便于在进行诊断时发现泄漏对象以及发生泄漏 的路径。在进行诊断的时候,发现泄漏类以及泄漏的路径是同时进行的,而 不是分步进行的。基于对对象分配的跟踪和记录,下面描述泄漏的诊断。
在进行诊断之前,需要对应用程序的虚拟机的堆进行访问。经过多次垃 圾回收当前堆中仅保存有存活的对象信息。就本发明而言,包含有所分配对 象的类型、分配时间、分配路径等信息。这些信息可以以上述与对象绑定的 标签的形式存在,也可以其他形式存在,例如可以专门设立一种分配路径管 理器将按来管理每个对象的分配时间以及分配路径直接的对应关系。
总体而言,首先,将标签中基于频带id和组id的组合相同的对象聚合 (aggregate)成一组。接着从具有最高频带的对象从其标签的最后俩个字段 中恢复出这些对象的分配路径。用这种方式找到的组数就是该路径分配对象 的年龄跨度或者年龄代数。获取该路径中的对象分配跨度或代数(span)以 便用于诊断泄漏。采用这种方式,可同时找出泄漏对象以及泄漏路径。
在较长的运行时间期间,泄漏导致在堆上具有不同年龄的相同类型的对 象的存在。对象的寿命是其幸免的垃圾回收的次数。该跨度计数是一种类型 的所有实例的不同寿命的数量或者代数。较低的跨度计数表示一类的所有实 例在存储器内已经存在了相同的时间。较高的跨度计数表示该运行的应用程 序正继续分配同一类新对象而没释放其更老的对象,程序通常不倾向于间隔 地分配长时间存活的对象。相反,他们倾向于集中性地分配长时间存活的对 象,或者分配对象只是为了在随后很短一段时间使用,这些对象随后一旦其 不再被需要就会立刻被清除。
基于以上理论,存活对象通过其标签被汇总以便诊断泄漏问题。如在前 面所提到的那样, 一个标签包括与分配路径上的层级相关的位置的频带id以
13及与将路径标签到对象上的满溢次数(round)相关的组id。每一次垃圾收集 都会清除清除堆上那些不被引用的、"死亡"的对象。如上面所提到的那样, 频带id以及组id的组合在不同时间间隔(至少间隔Tt)期间被绑定。时间 Tt与垃圾回收的时间间隔相关,能够用于标识对象的年龄。这样,标签中不 同频带id以及组id的组合区分了不同年龄的对象。基于以上分析,所有标签 中拥有相同的频带id以及组id组合的对象被分到一组,这样被一条分配路径 分配的对象被分到若干组内。分组的数量决定了该路径分配的对象的年龄代 数。分配最大年龄代数的对象的那些路径被辨识为候选泄漏路径。具有这些 候选路径标签的对象就是泄漏实例。图5所示的是该聚合的处理过程。
在进行聚合以及获知了哪些是嫌疑泄漏类之后,需要采用与将标签路径 绑定到对象上的处理相反的处理来确定分配中哪些是泄漏哪些不是泄漏,因 为分配位置以及分配路径具体内容对于诊断和修复泄漏来说是有很大帮助 的,因此遍历整个路径是必须的。为了解决这个问题,就要进行与将标签路 径绑定到对象上的处理相反的处理,从标签中恢复出确切的泄漏路径。该恢 复过程可见图3所示。从类型i的对象的最高频带为K (K>=1 )处的标签开 始,标签的一个字段(field)是"callee (被调用者)",其引用在频带(K-l) 处的方法,被在频带K处的方法调用。这样迭代的恢复出原始分配路径的各 层方法,所发现的方法链条就是分配路径。也就是说,路径的发现过程从最 高波段开始进行。
图6所示的是诊断一个应用程序所造成的内存泄漏的流程图。首先运行 一个应用程序,并在步骤S601处, 一种如后面将要描述的内存泄漏诊断装置 随着应用程序开始运行而开始监测在应用程序的运行时间(runtime)处对象 的分配以及内存的分配。在步骤S602处,内存泄漏诊断装置中的对象分配跟 踪器件跟踪应用程序在虚拟机上运行过程中的对象分配,并针对每一种类型 的对象,获取该当前对象的类型以及所分配的堆栈,为所有堆栈编码唯一的 id以及为每个对象赋予一个与一条分配路径相对应的唯一的id,并将这种对 应关系存储起来。然后在步骤S603处,将其中包含了该对象的类型id、其堆 栈的id、以及指向顶部方法签名的指针的标签与相应的对象绑定在一起。该 顶部方法签名并不在寄存器中。所有的方法签名都被编码并保存在代理中, 这种不同签名的系列表示了各种分配路径。因此,与对象绑定的标签包含了 该对象的分配路径以及对象的类型。在步骤S604处,将所有对象的标签保存在一个列表中。具体而言,就是采用如后面所述的分配路径管理器件来管理 该列表,从而管理列表中的标签中所包含的数据,即对象的类型id、其堆栈
的id、以及指向顶部方法签名的指针。在步骤S605处,经过一个预订的时间 间隔之后,例如经过了自动垃圾回收装置执行一次自动垃圾回收的预定间隔 之后,用于由对象的类型id以及堆栈的id的id的寄存器被修改以便存储具 有更高层级或波段的方法签名,从而使得以后所分配的对象与在该间隔之前 所分配的对象具有不同的年龄代数。所述的时间间隔可以是预定时间间隔, 例如垃圾回收间隔。所述寄存器的改变也可以通过具体的事件来触发。该具 体的时间可以是具有特定类型和堆栈的对象的总量达到了用户根据其应用程 序的存储器使用规模所规定的某种阈值,也可以是某种需要专门关注的事件。 在步骤S606处,用户需要进行内存泄漏诊断时,通过后面将要描述的分配路 径读取器件,从一个存储器中读取关于标签的列表以及位于堆中的存活的分 配对象的信息。随后在步骤S607中,从所读取的标签列表中提取各个标签, 并将所有存活的分配对象按照标签聚合曽不同的组。然后在步骤S608处,对 每个具有相同标签的组中的对象的总量进行排序,并将那些排序高的组中的 对象(即龄年代数较高的对象)所在的分配路径确定为嫌疑的内存泄漏路径。 应当理解上述方法为本发明的优选实施例,并非所有步骤对于解决本发明所
除非从上下文中能清楚一个步骤依赖于先执行的另一步骤。此外,步骤之间 可以有显著的时间间隔。
以上对本发明的内存泄漏的诊断方法进行了详细的描述。相对于现有技 术而言,这些方法具有以下优点用户无需制作引用图并对对象的引用图进 行分析、通过将分配时间与分配路径与分配对象的绑定可以直接获得与泄漏 嫌疑对象对应的分配路径、有助于修复泄漏,易于发现代码跟踪输入项以及 找到被分配的对象是如何被使用的、尤其是可以同时发现泄漏的对象以及能 够确定候选分配路径,并且该候选分配路径可以仅仅通过一次访问堆就可以 实现。该方法有助于将用户从瑣碎的中断和分析中解脱出来,防止系统进行 多重堆访问或堆转储,因此缩短了诊断的时间。此外,本发明的方法不需要 对现有的虚拟机进行任何修改、不需要对内部GC机制进行任何修改、不需 要对事件监听的去分配(de-allocation )、甚至不需要考虑对象的移动。
图7是采用上述方法的装置的一个实施例。如图7所示,根据本发明的诊断内存泄漏的装置700包括对象分配跟 踪器件701,用于跟踪应用程序70S在虚拟机712上运行过程中的对象分配, 从而获耳又对象的分配路径和分配时间;分配路径记录装置702,用于记录从 对象分配跟踪器件701传送来的每个对象的分配路径和分配时间;存储器 703,用于存储从分配路径记录器件702传送来的与对象相关的分配路径和分 配时间;分配路径管理器件704,用于管理存储器中所存储的数据,以及为 每个对象赋予一个与一条分配路径相对应的唯一的id并将这种对应关系以存 储在存储器中;用于应用程序的堆709,用于存储从分配路径记录器件702 传送来的分配对象的信息;分配路径读取器件705,用于读取所述堆中分配 对象的信息,并扫描存储器中存储的每个对象的id以及对应的分配路径信息, 以便针对每条分配路径整理由它分配的、并且还没有被回收的对象并根据每 个对象的分配时间计算该路径所分配同一类对象的年龄代数;分配路径排序 器件706,用于根据每条路径分配的、并且存活的对象的年龄代数对分配路 径进行排序;以及诊断报告器件707,用于对从分配路径排序器件传送来的 分配路径的排序数据进行分析,并将高排序的分配路径确定为可能存在内存 泄漏的分配路径报告给用户进行分析。
图8是采用上述方法的装置的另一个实施例。
如图8所示,根据本发明的诊断内存泄漏的装置800包括对象分配跟 踪器件801,用于跟踪应用程序808在虛拟机812上运行过程中对象的分配, 从而获取对象的分配路径和分配时间;分配路径记录装置802,用于在每个 所分配的对象上打上包含其分配路径与分配时间的对应关系的标签;用于应 用程序的堆809,用于存储从分配路径记录器件802传送来分配对象的信息; 分配路径读取器件805,针对每条分配路径直接按照标签从所述堆中读取由 它分配的、并且还没有被回收的对象并根据每个对象的分配时间计算该路径 所分配同一类对象的年龄代数;分配路径排序器件806,用于根据每条路径 分配的、并且存活的对象的年龄代数对分配路径进行排序;以及诊断报告器 件807,用于对从分配路径排序器件806传送来的分配路径的排序数据进行 分析,并将高排序的分配路径确定为可能存在内存泄漏的分配路径报告给用 户进行分析。
对于上述诊断内存泄漏的装置700和800,其还可以包括对象寿命管理 器件710以及810以及动态比特码器件711以及811。对象寿命管理器件710以及810用于按照对象分配时间来直接计算对象的年龄,避免直接将分配时
间放入所述堆中。动态比特码器件711以及811可使用二进制代码注入的方
法获取分配路径,替换直接读取运行时堆栈的内容以获取路径信息。
本发明的描述是为了示例说明的目的而提供的,而不旨在是彻底无遗漏 的,或者局限于所公开的实施例。很多修改和变更对于本领域的普通技术人 员将是清楚的。选择这些实施例是为了说明本发明的原理及其实际应用,并 且使得本领域的其他普通技术人员能够理解本发明,以便实现可能适于其他 预期用途的具有各种修改的各种实施例。
权利要求
1.一种诊断内存泄露的方法,包括跟踪应用程序在虚拟机上运行过程中的对象分配,从而获取并记录对象的分配路径和分配时间;以预定的时间间隔计算每一类对象在其分配路径的年龄代数;以及将其上具有高年龄代数对象的分配路径确定为可能存在内存泄漏的分配路径,并报告给用户以进行分析
2. 如权利要求1所述的诊断内存泄露的方法,其中,所述预定的时间间 隔是垃圾回收间隔或对应于特定类型和堆栈的对象的总量达到规定的阈值的 时间。
3. 如权利要求1或2所述的诊断内存泄露的方法,其中,获取并记录对 象的分配路径和分配时间的步骤包括为每个对象赋予一个与分配路径相对 应的p舉一的id。
4. 如权利要求3所述的诊断内存泄露的方法,其中,以预定的时间间隔 计算每一类对象在其分配路径其年龄代数的步骤包括基于每个对象的与分 配该对象的分配路径相对应id,确定其每个对象所属的分配路径,并针对每 条分配路径整理由它分配的、并且还没有被回收的对象并根据每个对象的分 配时间计算该路径所分配同一类对象的年龄代数。
5. 如权利要求3所述的诊断内存泄露的方法,其中,将其上具有高年龄 代数对象的分配路径确定为可能存在内存泄漏的分配路径的步骤包括根据 每条路径分配的、并且存活的同类对象的年龄代数对路径进行排序,以及对 分配路径的排序数据进行分析,并将高排序的分配路径确定为可能存在内存 泄漏的分配路径报告给用户进行分析。
6. 如权利要求5所述的诊断内存泄露的方法,其中所述跟踪应用程序在 虛拟机上运行过程中对象的分配采用一种数据结构来进行,该数据结构包含 了对象所属类的签名、对象计数、时间计数以及分配路径。
7. 如权利要求6所述的诊断内存泄露的方法,其中所述为每个对象赋予 一个与一条分配路径相对应的唯一的id,包括将每个对象的与分配路径相关 联的波段id以及组id包含在一种标签中并将标签与相应的对象绑定。
8. 如权利要求7所述的诊断内存泄露的方法,其中所述标签中还可以包含关于对象的类型、路径、方法以及被调用者的信息。
9. 如权利要求4所述的诊断内存泄露的方法,其中所述以预定的时间间 隔计算每一类对象在其分配路径其年龄代数从对象所属的分配路径的最高波段id开始。
10. 如权利要求4所述的方法,其中还包括在进行所述整理之前进行至少一次垃圾收集。
11. 一种诊断内存泄漏的装置,包括对象分配跟踪器件,跟踪应用程序在虚拟机上运行过程中的对象分配, 从而获取并记录对象的分配路径和分配时间;分配路径记录器件,用于记录从对象分配跟踪器件传送来的每个对象的 分配3各径和分配时间;用于应用程序的堆,用于存储从分配路径记录器件传送来的路径分配的 对象信息;分配路径读取器件,用于读取所述堆中路径分配的对象信息,并扫描存 储器中存储的每个对象的id以及对应的分配路径信息,以便针对每条分配路 径整理由它分配的、并且还没有被回收的对象并根据每个对象的分配时间计 算该路径所分配同一类对象的年龄代数;分配路径排序器件,用于根据每条路径分配的、并且存活的对象的年龄 代数把路径排序;以及进行分析,并将高排序的分配路径确定为可能存在内存泄漏的分配路径报告 给用户以进行分析。
12. 如权利要求11所述的诊断内存泄漏的装置,其中对象分配跟踪器件 采用 一种数据结构来进行对象分配的跟踪,该数据结构包含了对象所述的类 的签名、对象计数、时间计数以及分配路径。
13. 如权利要求11或12所述的诊断内存泄露的装置,其还包括对象寿 命管理器件用于按照对象分配时间来直接计算对象的年龄,避免直接将分配 时间放入所述堆中。
14. 如权利要求11所述的诊断内存泄露的装置,其还包括动态调码器, 其可使用二进制代码注入的方法获取分配路径,替换直接读取运行时堆栈的 内容以获取路径信息。
15. —种用于诊断内存泄漏的装置,包括对象分配跟踪器件,用于跟踪应用程序在虚拟机上运行过程中的对象分配,从而获取对象的分配路径和分配时间;分配路径记录器件,用于在每个所分配的对象上打上包含其分配路径与 分配对象的对应关系的标签;用于应用程序的堆,用于存储从分配路径记录器件传送来的路径分配的 对象信息;分配路径读取器件,对每条分配路径直接按照标签从所述堆中读取由它 分配的、并且还没有被回收的对象,并根据每个对象的分配时间计算该路径 所分配同一类对象的年龄代数;分配路径排序器件,用于根据每条路径分配的、并且存活的对象的年龄 代数把路径排序;以及诊断报告器件,用于对从分配路径排序器传送来的分配路径的排序数据 进行分析,并将高排序的分配路径确定为可能存在内存泄漏的分配路径报告 给用户进行分析。
16. 如权利要求15所述的诊断内存泄漏的装置,其中对象分配跟踪器件 采用一种数据结构来进行对象分配的跟踪,该数据结构包含了对象所述的类 的签名、对象计数、时间计数以及分配路径。
17. 如权利要求15所述的诊断内存泄露的装置,其中所述分配路径记录 器件通过将标签与相应的对象绑定来记录与分配对象相关的信息。
18. 如权利要求17所述的诊断内存泄露的装置,其中所述标签中还可以 包含关于对象的类型、路径、方法以及被调用者的信息。
19. 如权利要求15-19任意一项所述的诊断内存泄露的装置,其还包括 对象寿命管理器件用于按照对象分配时间来直接计算对象的年龄,避免直接 将分配时间放入所述对象标签中。
20. 如权利要求19所述的诊断内存泄露的装置,其还包括动态变码器, 其可使用二进制代码注入的方法获取分配路径,替换直接读取运行时堆栈的 内容以获取路径信息。
全文摘要
一种诊断内存泄露的方法和装置。所述方法包括跟踪应用程序在虚拟机上运行过程中的对象分配,从而获取对象的分配路径和分配时间;记录每个对象的分配路径和分配时间;为每个对象赋予一个与一条分配路径相对应的唯一的ID;基于每个对象的与分配该对象的分配路径相对应ID,确定其每个对象所属的路径;针对每条分配路径整理由它分配的、并且还没有被回收的对象并根据这些对象的分配时间计算该路径所分配同一类对象的“年龄代数”;根据每条路径分配的、并且存活的同类对象的年龄代数对路径进行排序;以及对分配路径的排序数据进行分析,排序越高的分配路径,越有可能是引入内存泄漏。据此,可能存在内存泄漏的分配路径被挑选、报告给用户进行分析。本发明还涉及一种执行上述方法的装置。
文档编号G06F9/50GK101615143SQ200810131740
公开日2009年12月30日 申请日期2008年6月27日 优先权日2008年6月27日
发明者刘天成, 影 李, 李欣慧, 滕启明, 滢 陈 申请人:国际商业机器公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1