Android中内存泄露代码优化及检测

  内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。

        正如下文所说,内存泄漏与许多其他问题有着相似的症状,并且通常情况下只能由那些可以获得程序源代码的程序员才可以分析出来。然而,有不少人习惯于把任何不需要的内存使用的增加描述为内存泄漏,即使严格意义上来说这是不准确的。

一、内存泄露

        内存泄漏会因为减少可用内存的数量从而降低计算机的性能。最终,在最糟糕的情况下,过多的可用内存被分配掉导致全部或部分设备停止正常工作,或者应用程序崩溃。

        内存泄漏可能不严重,甚至能够被常规的手段检测出来。在现代操作系统中,一个应用程序使用的常规内存在程序终止时被释放。这表示一个短暂运行的应用程序中的内存泄漏不会导致严重后果。

        在以下情况,内存泄漏导致较严重的后果:

        1)程序运行后置之不理,并且随着时间的流失消耗越来越多的内存(比如服务器上的后台任务,尤其是嵌入式系统中的后台任务,这些任务可能被运行后很多年内都置之不理);

        2)新的内存被频繁地分配,比如当显示电脑游戏或动画视频画面时;

        3)程序能够请求未被释放的内存(比如共享内存),甚至是在程序终止的时候;

        4)泄漏在操作系统内部发生;

        5)泄漏在系统关键驱动中发生;

        6)内存非常有限,比如在嵌入式系统或便携设备中;

        7)当运行于一个终止时内存并不自动释放的操作系统(比如AmigaOS)之上,而且一旦丢失只能通过重启来恢复。

二、内存泄漏检测工具

        当一个Java对象已经没有其他对象引用它时,Java的垃圾回收器会将其回收并释放内存。

        一个Java的Heap Dump文件指的是在一个时间点上Java对象的内存镜像导出文件。它包括了所有的对象、字段、原始类型和对象引用。它可以指示当JVM产生OutOfMemory错误的情况下自动创建一个堆转储。

        使用Eclipse MAT(Eclipse Memory Analyser),有助于图形化基于Java堆转储的对象引用,并提供工具以发现潜在的内存泄露。为了能让Java虚拟机(JVM)在发生OutOfMemory错误时生成内存镜像文件,我们可以使用-XX:+HeapDumpOnOutOfMemoryError选项,如图21.1所示。

        安装Eclipse MAT的步骤如下:

        1)启动Eclipse,点击Help -> Intall New Software...;

        2)点击输入栏右侧小箭头,选择"Juno"(不同版本要找到和自己版本名称对应的选项);

        3)等待列表更新完毕,找到并展开"General Purpose Tools";

        4)选中并下载其中的"Memory Analyser (Incubation)"和"Memory Analyser (Charts)"两项。

        5)之后根据提示进行安装。

三、MAT使用示例

        1)创建工程

        新建Android 工程 "com.devdiv.test.mat_test"。并且新建如下类,然后运行该工程。

[代码]java代码:

package com.devdiv.test.mat_test;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {

    List<String> list = new ArrayList<String>();
//    private PersonInfo person = new PersonInfo();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new Thread () {
            @Override
            public void run() {
                while (true){
                	MainActivity.this.list.add("OutOfMemoryError soon");
                }
            }
        }.start();
    }

}

 2)分析内存

        要获得.hprof内存镜像文件,你可以在进程运行过程中,切换到DDMS的透视图页面,选中您要查看内存镜像的进程,点击“Dump HPROF file”即可。

 

图16-1  内存镜像文件分析

        生成的hprof文件会默认使用MAT打开,选择“Leak Suspects Report”后,点击Finish按钮。

 

图16-2  用MAT打开内存镜像文件

        经过一段时间的初始化后,就能够直观地看到关于内存泄露的饼图,如下图所示:

 

图16-3  内存泄露饼图

        然后就可以查看相关的内存泄露,如下图所示:

 

图16-4  内存泄露树形图

时间: 2024-12-22 18:18:27

Android中内存泄露代码优化及检测的相关文章

八个造成 Android 应用内存泄露的原因

本文讲的是八个造成 Android 应用内存泄露的原因, 诸如 Java 这样的 GC (垃圾回收)语言的一个好处就是免去了开发者管理内存分配的必要.这样降低了段错误导致应用崩溃或者未释放的内存挤爆了堆的可能性,因此也能编写更安全的代码.不幸的是,Java 里仍有一些其他的方式会导致内存"合理"地泄露.最终,这意味着你的 Android 应用可能会浪费一些非必要内存,甚至出现 out-of-memory (OOM) 错误. 传统的内存泄露发生的时机是:所有的相关引用已不在域范围内,你忘

控制台和MFC中内存泄露工具vld的使用

   最近想检测下项目中内存泄露的情况,选中了vld这款.在查找使用方法的时候,大都是控制台下的示例,添加到main函数所在的源文件上.换成MFC就纠结了,不知道添加到哪里去.本文记录控制台和MFC中的使用vld过程.    vld资源:    1).大家可以移步下边的网址下载:     http://vld.codeplex.com/releases/view/82311    2).也可以到我的资源中下载:     http://download.csdn.net/detail/alex_m

Android webview 内存泄露的解决方法

Android webview 内存泄露的解决方法 最近在activity嵌套webview显示大量图文发现APP内存一直在涨,没法释放内存,查了很多资料,大概是webview的一个BUG,引用了activity导致内存泄漏,所以就尝试传递getApplicationContext. 1.避免在xml直接写webview控件,这样会引用activity,所以在xml写一个LinearLayout,然后 linearLayout.addView(new MyWebview(getApplicati

Android应用内存泄露分析、改善经验总结

前言 通过这几天对好几个应用的内存泄露检测和改善,效果明显: 完全退出应用时,手动触发GC,从原来占有内存100多M降到低于20M: 手动触发GC后,通过adb shell dumpsys meminfo packagename -d查看Activity和View的数量也趋近于0了(没有做到归零是因为SDK中存在内存泄露,需要中间层去处理): 发现了一个SDK中的内存泄露(Android InputMethodManager 导致的内存泄露及解决方案): 发现一个MTK Webview的内存泄露

详解Java语言中内存泄漏及如何检测问题

Java的一个重要优点就是通过垃圾收集器(Garbage Collection,GC)自动管理内存的回收,程序员不需要通过调用函数来释放内存.因此,很多程序员认为Java不存在内存泄漏问题,或者认为即使有内存泄漏也不是程序的责任,而是GC或JVM的问题.其实,这种想法是不正确的,因为Java也存在内存泄露,但它的表现与C++不同. 随着越来越多的服务器程序采用Java技术,例如JSP,Servlet, EJB等,服务器程序往往长期运行.另外,在很多嵌入式系统中,内存的总量非常有限.内存泄露问题也

Android中内存优化的那些事 - 一个有关图片的优化记录

客服群里叫喊着:这个用户图片不显示了,那个用户图片也不显示了.我拿着手上一切正常的测试机,what the hell-- 默默地打开bugly.   满园春色关不住,遍地内存溢出来!是的,又闯祸了! 内存问题永远是既陌生又熟悉的话题,而且大多数都发生在一个叫作用户家的手机上.安卓系统本身不断的在优化,三方框架也逐渐成熟,外加手机厂商的大内存加持,似乎内存问题变得少见,但还是不能忽视. 借着这次修复内存问题的记录,分享一些"自以为"的解决思路,仅供参考.ok,let's go! 修复问题

如何避免iPhone应用中内存泄露

  创建对象时,所有权通过alloc.new.或者copy的方式建立,之后通过调用retain或者通过Cocoa函数来分配和复制对象的所有权. 内存释放有两种方式,一种方法是明确地请求释放对象的所有权,另一种方法则是使用自动释放池(auto-release pool). 所有权的背后是一个和引用有关的运算系统,iPhone SDK的大多数对象使用这个系统,彼此之间建立着很强的引用和参照. 当你创建一个对象时,引用值为1,调用一次retain则对象的引用值加1,调用一次release则对象的引用值

避免 Android中Context引起的内存泄露_Android

Context是我们在编写Android程序经常使用到的对象,意思为上下文对象. 常用的有Activity的Context还是有Application的Context.Activity用来展示活动界面,包含了很多的视图,而视图又含有图片,文字等资源.在Android中内存泄露很容易出现,而持有很多对象内存占用的Activity更加容易出现内存泄露,开发者需要特别注意这个问题. 本文讲介绍Android中Context,更具体的说是Activity内存泄露的情况,以及如何避免Activity内存泄

避免 Android中Context引起的内存泄露

Context是我们在编写Android程序经常使用到的对象,意思为上下文对象. 常用的有Activity的Context还是有Application的Context.Activity用来展示活动界面,包含了很多的视图,而视图又含有图片,文字等资源.在Android中内存泄露很容易出现,而持有很多对象内存占用的Activity更加容易出现内存泄露,开发者需要特别注意这个问题. 本文讲介绍Android中Context,更具体的说是Activity内存泄露的情况,以及如何避免Activity内存泄