`

内存泄漏调试经验分享

阅读更多

( 查询数据库没有关闭游标

描述:

    程序中经常会进行查询数据库的操作,但是经常会有使用完毕Cursor 后没有关闭的情况。如果我们的查询结果集比较小,对内存的消耗不容易被发现,只有在常时间大量操作的情况下才会复现内存问题,这样就会给以后的测试和问题排查带来困难和风险。

 

示例代码:

Cursor cursor = getContentResolver().query(uri ...);

if (cursor.moveToNext()) {

    ... ... 

}

 

修正示例代码:

Cursor cursor = null;

try {

    cursor = getContentResolver().query(uri ...);

    if (cursor != null && cursor.moveToNext()) {

        ... ... 

    }

} finally {

    if (cursor != null) {

        try { 

            cursor.close();

        } catch (Exception e) {

            //ignore this

        }

    }

 

( 构造 Adapter 时,没有使用缓存的  convertView

描述:

    以构造ListView BaseAdapter 为例,在 BaseAdapter 中提高了方法:

public View getView(int position, View convertView, ViewGroup parent)

来向ListView 提供每一个 item 所需要的 view 对象。初始时 ListView 会从 BaseAdapter 中根据当前的屏幕布局实例化一定数量的 view 对象,同时 ListView 会将这些 view 对象缓存起来。当向上滚动 ListView 时,原先位于最上面的 list item view 对象会被回收,然后被用来构造新出现的最下面的 list item 。这个构造过程就是由 getView() 方法完成的, getView() 的第二个形参  View convertView 就是被缓存起来的 list item view 对象 ( 初始化时缓存中没有 view 对象则 convertView null)

    由此可以看出,如果我们不去使用convertView ,而是每次都在 getView() 中重新实例化一个 View 对象的话,即浪费资源也浪费时间,也会使得内存占用越来越大。 ListView 回收 list item view 对象的过程可以查看 :

android.widget.AbsListView.java --> void addScrapView(View scrap) 方法。

 

示例代码:

public View getView(int position, View convertView, ViewGroup parent) {

    View view = new Xxx(...);

    ... ...

    return view;

}

 

修正示例代码:

public View getView(int position, View convertView, ViewGroup parent) {

    View view = null;

    if (convertView != null) {

        view = convertView;

        populate(view, getItem(position));

        ...

    } else {

        view = new Xxx(...);

        ...

    }

    return view;

 

( ) Bitmap 对象不在使用时调用 recycle() 释放内存

描述:

    有时我们会手工的操作Bitmap 对象,如果一个 Bitmap 对象比较占内存,当它不在被使用的时候,可以调用 Bitmap.recycle() 方法回收此对象的像素所占用的内存,但这不是必须的,视情况而定。可以看一下代码中的注释:

    /**

     * Free up the memory associated with this bitmap's pixels, and mark the

     * bitmap as "dead", meaning it will throw an exception if getPixels() or

     * setPixels() is called, and will draw nothing. This operation cannot be

     * reversed, so it should only be called if you are sure there are no

     * further uses for the bitmap. This is an advanced call, and normally need

     * not be called, since the normal GC process will free up this memory when

     * there are no more references to this bitmap.

     */

( 释放对象的引用

描述:

    这种情况描述起来比较麻烦,举两个例子进行说明。

示例A

假设有如下操作

public class DemoActivity extends Activity {

    ... ...

    private Handler mHandler = ...

    private Object obj;

    public void operation() {

       obj = initObj();

       ...

       [Mark]

       mHandler.post(new Runnable() {

            public void run() {

               useObj(obj);

            }

       });

    }

}

    我们有一个成员变量 obj ,在 operation() 中我们希望能够将处理 obj 实例的操作 post 到某个线程的 MessageQueue 中。在以上的代码中,即便是 mHandler 所在的线程使用完了 obj 所引用的对象,但这个对象仍然不会被垃圾回收掉,因为 DemoActivity.obj 还保有这个对象的引用。所以如果在 DemoActivity 中不再使用这个对象了,可以在 [Mark] 的位置释放对象的引用,而代码可以修改为:

... ...

public void operation() {

    obj = initObj();

    ...

    final Object o = obj;

    obj = null;

    mHandler.post(new Runnable() {

        public void run() {

            useObj(o);

        }

    }

}

... ...

 

示例B:

    假设我们希望在锁屏界面(LockScreen) 中,监听系统中的电话服务以获取一些信息 ( 如信号强度等 ) ,则可以在 LockScreen 中定义一个 PhoneStateListener 的对象,同时将它注册到 TelephonyManager 服务中。对于 LockScreen 对象,当需要显示锁屏界面的时候就会创建一个 LockScreen 对象,而当锁屏界面消失的时候 LockScreen 对象就会被释放掉。

    但是如果在释放LockScreen 对象的时候忘记取消我们之前注册的 PhoneStateListener 对象,则会导致 LockScreen 无法被垃圾回收。如果不断的使锁屏界面显示和消失,则最终会由于大量的 LockScreen 对象没有办法被回收而引起 OutOfMemory, 使得 system_process 进程挂掉。

    总之当一个生命周期较短的对象A ,被一个生命周期较长的对象 B 保有其引用的情况下,在 A 的生命周期结束时,要在 B 中清除掉对 A 的引用。

( 其他

    Android应用程序中最典型的需要注意释放资源的情况是在 Activity 的生命周期中,在 onPause() onStop() onDestroy() 方法中需要适当的释放资源的情况。由于此情况很基础,在此不详细说明,具体可以查看官方文档对 Activity 生命周期的介绍,以明确何时应该释放哪些资源

_Android_内存泄漏调试.pdf,以下有下载:

分享到:
评论

相关推荐

    Android 内存泄漏调试经验分享

    ### Android内存泄漏调试经验分享 #### 一、概述 在Android开发中,内存泄漏是一个常见且需要重点关注的问题。由于Android设备通常配置有限,尤其是内存资源较为紧张,因此开发者需要格外注意避免内存泄漏的发生,...

    Android内存管理

    **2.2 Android内存泄漏调试经验分享** 在实践中,开发者可以通过以下几种方法来调试和修复内存泄漏: - **分析堆栈快照**: 使用工具分析堆栈快照,找出哪些对象没有被正确释放。 - **检查生命周期管理**: 确保...

    vc调试经验分享 vc调试合集

    当遇到空指针异常或内存泄漏时,可以使用“内存窗口”查看内存分配和使用情况,或者使用Visual Leak Detector等工具辅助检测内存泄漏。同时,注意分析堆栈信息,通过调用堆栈回溯找到问题源头。 在多线程环境下,...

    C++程序检测内存泄漏的方法分享

    下面结合我的实际经验,整理下常见定位内存泄漏的方法。 注意:我们的分析前提是Release版本,因为在Debug环境下,通过VLD这个库或者CRT库本身的内存泄漏检测函数能够分析出内存泄漏,相对而言比较简单。而服务器有...

    软件调试经验案例手册|软件调试经验案例.zip

    通过这些案例,读者可以学习到如何分析日志、追踪堆栈、使用断点和变量监视,以及如何进行性能剖析和内存泄漏检测。此外,了解如何在设计阶段引入健壮性,例如编写单元测试、使用静态代码分析工具,也是避免问题的...

    浅谈VueJS SSR 后端绘制内存泄漏的相关解决经验

    此外,社区中关于VueJS SSR内存泄漏的讨论和经验分享也非常值得参考,因为它们往往包含了实践中发现的独特问题和有效的解决方案。通过交流和学习,我们可以更好地理解和解决VueJS SSR中的内存泄漏问题,提升应用的...

    c++出错调试经验

    本篇文章将重点分享一些在使用Visual Studio 2008 (VS2008)进行C++编程时,可能会遇到的不易察觉的错误及其调试方法。 1. **未初始化的变量**:这是一个常见的问题,程序员可能忘记初始化变量,导致程序运行时产生...

    Windows 驱动高级调试

    pool`命令检查内存池分配情况,以查找内存泄漏。 7. **调试内核模式崩溃**:在内核模式下,WinDbg可以帮助调试蓝屏错误(BSOD)。分析蓝屏转储文件(dump file)可以揭示崩溃时的系统状态。 8. **符号文件和源代码...

    《Windows程序调试》完整书签版+在线笔记心得问答交流.rar

    书中提供的在线笔记心得问答交流部分,很可能包含了大量的实例分析和读者的经验分享,这对于深化理解和应用调试技术非常有价值。 通过阅读《Windows程序调试》这本书,开发者可以系统地学习和掌握Windows环境下的...

    软件调试 张英奎编著

    调试技巧方面,张英奎可能会分享一些实战经验,比如如何有效利用日志输出、单元测试和代码审查来辅助调试。日志输出可以在程序运行时记录关键信息,帮助定位问题。单元测试则是通过编写独立的小测试来验证代码功能,...

    GDB调试程序[陈皓]&GDB调试工具指南

    此外,陈皓可能还会分享一些高级技巧,如使用GDB的Python扩展进行更复杂的调试任务,或者如何结合GDB与其他工具(如Valgrind)一起使用来检测内存泄漏和其他资源管理问题。 另一方面,《GDB调试工具指南》可能是一...

    VC 调试教程 解密版

    #### 经验分享 - **跟踪技巧**:深入学习跟踪技术,如使用MFC的TRACE宏、ASSERT宏、ASSERT_VALID宏等,有效定位问题。 - **内存管理**:熟练掌握CMemoryState类的使用,有效监测内存使用情况,及时发现并处理内存...

    一款针对开发者和测试者的调试工具

    2. **内存泄漏检测**:工具内置了内存泄漏检测功能,能实时监控应用的内存使用情况,及时发现可能导致应用崩溃的内存问题。 3. **CPU与内存性能分析**:提供CPU和内存的实时监控图表,帮助开发者了解应用运行时的...

    内存搜索工具VE,内存搜索

    这对于分析程序行为、定位内存泄漏等问题非常有帮助。 5. **脚本支持**:高级用户可以通过编写脚本来自动化内存操作,实现更复杂的任务,如自动搜索、修改或跟踪内存变化。这大大提高了工作效率,特别是在处理大量...

    VxWorks调试

    - **文档记录**:及时记录调试过程中的发现和解决方案,方便后续参考或分享经验。 #### 六、总结 通过本文的介绍,我们可以了解到VxWorks提供的强大调试功能,这些工具和技术不仅能够帮助开发者高效地完成软件调试...

    程序调试思想与实践.rar

    6. **内存泄漏与性能分析**:内存泄漏可能导致程序崩溃或性能下降。学习如何检测和修复内存泄漏,以及如何使用性能分析工具优化代码,是提升程序稳定性和效率的重要部分。 7. **调试Web应用和数据库**:对于Web应用...

    java经验分享

    ### Java开发经验分享:提升代码质量和效率的关键实践 在Java开发领域,良好的编码习惯和实践是确保项目成功、代码质量及团队协作效率的关键。以下是从标题、描述、标签以及部分内容中提炼出的重要知识点,旨在帮助...

    sun dbx 调试手册

    - 调试内存错误:如空指针引用、数组越界、内存泄漏等。 - 性能优化:通过分析程序运行时间和内存使用情况,找出瓶颈并进行优化。 - 复杂逻辑分析:在多线程或者并发环境中,dbx可以帮助理解和调试复杂的执行流程...

Global site tag (gtag.js) - Google Analytics