对象自身的无参数方法调用,在方法体中创建对 “this”关键字的引用,没有及时释放而导致内存泄露。
下面这段程序是 UIComponent 的 setFocus() 的源代码:
清单3.UIComponent.as
public function setFocus():void { var sm:ISystemManager = systemManager; if (sm&&(sm.stage ||sm.useSWFBridge())) { if (UIComponentGlobals.callLaterDispatcherCount== 0) { sm.stage.focus = this; UIComponentGlobals.nextFocusObject= null; } ...
在调用 setFocus() 方法后, 通过 sm.stage.focus = this,全局对象 systemManager 产生了对 UIComponent 的引用。 如果之后不做处理,就会造成内存泄露。这里只是举个例子,对于 UIComponent 的 setFocus() 方法 Flex 已经做了处理,不会造成内存泄露,大家可以放心使用。
但是在日常 的编程过程中,一定要注意这种非常隐蔽的情况。
隐式引用
隐式引用最常见的情况就是添加事件监听器。a.addEventListener ("Leak", b.leakHandler);
a 对象的“listener”属性创建了一个指向 b 对象 leakHandler 方法的引用,如下图所示,
图 1. 注册事件监听器引用图
即使把 b 置为 null,只要 a 对象没有被回收,b 也不会被回收,从而导致内存泄露。通过弱引用方 式可以避免这种内存泄露,在后面的章节会有详细描述。
Flex Builder Profiler 工具简介
Adobe 公司在 Flex Builder 3 中提供了一个 Profiler 工具,用于 Flex 内 存诊断和性能调优。本文重点介绍 Profiler 用于内存诊断方面的功能。
Profiler 的启动
在 Flex 开发视图,选择主入口文件并点击鼠标右键 ->Profile As- >Flex Application 启动 Profiler 工具。
如下图所示:
图 2. 本地启动 Profiler
Profiler 参数配置
启动后,系统首先弹出对话框让用户配置 Profiler 的参数,如下图所示:
图 3. Profiler 参数配置
选项 “Enable performance profiling”是用做性能调优的,主要用来找到响应时间 的瓶颈。在做内存调试时,将这一项勾掉。
选项“Generate object allocation stack traces”选项可以跟踪对象创建的整个过程,这个功能非常消耗系 统资源,在调试的初期,目的是找到内存泄露的对象,而不关心它的创建过程,因此先不要 选择该项。
配置完毕,点击 Resume 按钮继续执行。 几秒钟之后,Profiler 工具开始运行,如下图所示:
图 4. Profiler 运行主界面
Profiler 常用功能
“Profile”窗口显示正在运行的 SWF 应用,选中 后,窗口上的一系列的按钮就变成可用状态,如下图所示:
图 5. Profiler 窗口
这里简要介绍一下和内存调试相关的按钮的功能:
图 5 中 1“Run Garbage Collector”,点击该按钮,会强制执行一次内存回收。
图 5 中 2“Take Memory Sanpshot”,在运行的任何时刻,点击该按钮,系统首先会自动执行一次强制 内存回收,然后捕获一帧内存快照,作为当前正在运行的应用的子对象,如下图所示:
图 6. 捕获内存快照
双击这帧内存快照,会在下部窗口打开一个页签,显示该内存快照中的对象,包括对象所 在的包,实例数目和百分比,所占内存和百分比,如下图所示:
图 7. 内存快照中的 对象
图 5 中 3“Find Loitering Objects”,找出“游荡对象”。该 按钮需要同时选中两帧内存快照(按住 Ctrl 键点选内存快照)才有用,
如下图所示
图 8. 选中两帧内存快照
它的作用是通过对比两帧内存快照,找出在后一帧内存快照中存在而在前一帧内存快照中 不存在的对象。在某些特定的场景中,该功能能够迅速找到内存泄露的对象。
利用 Profiler 工具诊断内存泄露 内存快照对比法诊断内存泄露 Flex 应用内存泄 露的最直观表象是当用户进行某些相同操作时,内存和对象实例会持续增加,即使进行了垃 圾回收,内存也不会回到原始的水平。 在上一章节中,我们了解了 Profiler 的主要 功能,它可以在任何时刻捕获当时的内存快照。那么可以想象,如果每当用户进行一次相同 的操作时,我们就捕获一帧内存快照,通过对比几帧快照,找出持续增加的对象实例,就可 以发现是哪些对象导致了内存泄露,从而发现程序中的漏洞,最终解决问题。