android内存泄漏测试

要测内存泄漏呢,可以反复进入某一项操作,如反复进入联系人详情后返回键,观察内存的值是否有上升的趋势。

测试方法:

1.创建自动化测试脚本,每操作一次获取一次内存值,然后把内存值导出到文件中,制作成曲线图,就可以很直观的看见是否存在内存泄漏了。曾经用Uiautomator做过一次内存泄漏的脚本,如下:

package demotest;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiScrollable;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;

public class MemoryLeak extends UiAutomatorTestCase {
    // 应用包名
    static final String packageName = "com.android.phone";

    // 测试次数
    static final int counts = 500;
    public static void main(String[] args) {
        String jarName, testClass, testName, androidId;
        jarName = "demotest";
        testClass = "demotest.MemoryLeak";
        testName = "testScene_03";
        androidId = "3";
        new UiAutomatorHelper(jarName, testClass, testName, androidId);

    }

     // 场景一:打开/退出联系人

    public void testScene_01() throws IOException {
        File mTxt = mkFile("01");// 创建文件
        FileOutputStream fos = null;// 以字节流的形式读取
        fos = new FileOutputStream(mTxt);
        for (int i = 0; i < counts; i++) {
            scene_01();// 执行场景一的case
            sleep(2000);// 延迟2s
            String mMemory = memory(packageName);// 读取每一次的memory
            sleep(2000);
            byte[] b1 = (mMemory + "\n").getBytes();
            fos.write(b1);
        }
        fos.close();
    }

    //场景二:查看联系人
    public void testScene_02() throws IOException
    {
        File mTxt = mkFile("02");// 创建文件
        FileOutputStream fos = null;// 以字节流的形式读取
        fos = new FileOutputStream(mTxt);
        scene_01();//打开联系人
        for(int i=0;i<counts;i++)
        {
            getUiDevice().click(334, 416);
            sleep(1000);
            getUiDevice().pressBack();
            String mMemory = memory(packageName);// 读取每一次的memory
            sleep(2000);
            byte[] b1 = (mMemory + "\n").getBytes();
            fos.write(b1);
        }

        fos.close();
        getUiDevice().pressBack(); // 退出联系人
    }

   //添加联系人
    public void testScene_03() throws IOException, UiObjectNotFoundException
    {
        File mTxt = mkFile("03");// 创建文件
        FileOutputStream fos = null;// 以字节流的形式读取
        fos = new FileOutputStream(mTxt);
        scene_01();//打开联系人
        for(int i=0;i<counts;i++)
        {
            UiObject add=new UiObject(new UiSelector().resourceId("com.aurora:id/aurora_action_bar_item"));
            add.clickAndWaitForNewWindow();
            UiObject name=new UiObject(new UiSelector().text("请输入姓名"));
            name.setText("penghong");
            sleep(500);
            UiObject number=new UiObject(new UiSelector().text("请输入号码"));
            number.setText("15079034630");
            sleep(1000);
            new UiObject(new UiSelector().text("确定")).clickAndWaitForNewWindow();
            getUiDevice().pressBack();
            sleep(2000);// 延迟2s
            String mMemory = memory(packageName);// 读取每一次的memory
            sleep(2000);
            byte[] b1 = (mMemory + "\n").getBytes();
            fos.write(b1);
        }
        fos.close();
        getUiDevice().pressBack();
        getUiDevice().pressBack();
    }
    //删除联系人
    public void testScene_04() throws IOException, UiObjectNotFoundException
    {
        File mTxt = mkFile("04");// 创建文件
        FileOutputStream fos = null;// 以字节流的形式读取
        fos = new FileOutputStream(mTxt);
        scene_01();//打开联系人
        for(int i=0;i<counts;i++)
        {
            getUiDevice().swipe(550,395,215,402,40);
            sleep(1000);
            new UiObject(new UiSelector().resourceId("com.aurora:id/aurora_rubbish")).clickAndWaitForNewWindow();
            new UiObject(new UiSelector().text("确定")).clickAndWaitForNewWindow();
            sleep(500);
            String mMemory = memory(packageName);// 读取每一次的memory
            sleep(2000);
            byte[] b1 = (mMemory + "\n").getBytes();
            fos.write(b1);
        }
        fos.close();
        getUiDevice().pressBack();
    }

     // 场景一:打开/退出拨号盘

    public void testScene_05() throws IOException {
        File mTxt = mkFile("05");// 创建文件
        FileOutputStream fos = null;// 以字节流的形式读取
        fos = new FileOutputStream(mTxt);
        for (int i = 0; i < counts; i++) {
            scene_001();
            sleep(2000);// 延迟2s
            String mMemory = memory(packageName);// 读取每一次的memory
            sleep(2000);
            byte[] b1 = (mMemory + "\n").getBytes();
            fos.write(b1);
        }
        fos.close();
    }

    //拨号盘中界面切换
    public void testScene_06() throws IOException
    {
        File mTxt = mkFile("06");// 创建文件
        FileOutputStream fos = null;// 以字节流的形式读取
        fos = new FileOutputStream(mTxt);
        scene_001();
        for(int i=0;i<counts;i++)
        {
            getUiDevice().click(134, 1230);
            sleep(500);
            getUiDevice().click(373, 1248);
            sleep(500);
            getUiDevice().click(630, 1250);
            sleep(500);
            String mMemory = memory(packageName);// 读取每一次的memory
            sleep(2000);
            byte[] b1 = (mMemory + "\n").getBytes();
            fos.write(b1);
        }
        fos.close();
        getUiDevice().pressBack();
    }
    //反复进入电话帮
    public void testScene_07() throws IOException
    {
        File mTxt = mkFile("07");// 创建文件
        FileOutputStream fos = null;// 以字节流的形式读取
        fos = new FileOutputStream(mTxt);
        scene_001();
        for(int i=0;i<counts;i++)
        {
            getUiDevice().click(373, 1248);
            sleep(500);
            String mMemory = memory(packageName);// 读取每一次的memory
            sleep(2000);
            byte[] b1 = (mMemory + "\n").getBytes();
            fos.write(b1);
        }
        fos.close();
        getUiDevice().pressBack();
    }

    //拨号盘搜索联系人
    public void testScene_08() throws IOException, UiObjectNotFoundException
    {
        File mTxt = mkFile("08");// 创建文件
        FileOutputStream fos = null;// 以字节流的形式读取
        fos = new FileOutputStream(mTxt);
        scene_001();
        getUiDevice().click(386, 1223);
        sleep(500);
        if(new UiObject(new UiSelector().resourceId("com.android.contacts:id/yulore_superyellowpage_et_search")).exists())
        {
            getUiDevice().click(386, 1223);
            sleep(500);
        }
        for(int i=0;i<counts;i++)
        {
            new UiObject(new UiSelector().resourceId("com.android.contacts:id/aurora_one")).click();
            new UiObject(new UiSelector().resourceId("com.android.contacts:id/aurora_three")).click();
            new UiObject(new UiSelector().resourceId("com.android.contacts:id/aurora_zero")).click();
            new UiObject(new UiSelector().resourceId("com.android.contacts:id/aurora_deleteButton")).longClick();
            String mMemory = memory(packageName);// 读取每一次的memory
            sleep(2000);
            byte[] b1 = (mMemory + "\n").getBytes();
            fos.write(b1);
        }
        fos.close();
        getUiDevice().pressBack();
    }

    //拨号盘呼叫
    public void testScene_09() throws IOException, UiObjectNotFoundException
    {
        File mTxt = mkFile("09");// 创建文件
        FileOutputStream fos = null;// 以字节流的形式读取
        fos = new FileOutputStream(mTxt);
        scene_001();
        getUiDevice().click(386, 1223);
        sleep(500);
        if(new UiObject(new UiSelector().resourceId("com.android.contacts:id/yulore_superyellowpage_et_search")).exists())
        {
            getUiDevice().click(386, 1223);
            sleep(500);
        }
        for(int i=0;i<counts;i++)
        {
            new UiObject(new UiSelector().resourceId("com.android.contacts:id/aurora_one")).click();
            new UiObject(new UiSelector().resourceId("com.android.contacts:id/aurora_zero")).click();
            new UiObject(new UiSelector().resourceId("com.android.contacts:id/aurora_zero")).click();
            new UiObject(new UiSelector().resourceId("com.android.contacts:id/aurora_eight")).click();
            new UiObject(new UiSelector().resourceId("com.android.contacts:id/aurora_six")).click();
            new UiObject(new UiSelector().resourceId("com.android.contacts:id/aurora_dialButton")).click();
            sleep(3000);
            new UiObject(new UiSelector().text("结束通话")).clickAndWaitForNewWindow();
            String mMemory = memory(packageName);// 读取每一次的memory
            sleep(2000);
            byte[] b1 = (mMemory + "\n").getBytes();
            fos.write(b1);
        }
        fos.close();
        getUiDevice().pressBack();
    }

    //打开联系人
    public void scene_01() {
        getUiDevice().pressHome();
        UiScrollable deckViews = new UiScrollable(
                new UiSelector().scrollable(true));
        deckViews.setAsHorizontalList();
        UiObject sApp;
        try {
            sApp = deckViews
                    .getChildByText(
                            new UiSelector()
                                    .className(android.widget.TextView.class
                                            .getName()), "联系人");
            sApp.clickAndWaitForNewWindow();
        } catch (UiObjectNotFoundException e) {
            e.printStackTrace();
        }
        //getUiDevice().pressBack();
    }

    //打开拨号盘
    public void scene_001() {
        getUiDevice().pressHome();
        UiScrollable deckViews = new UiScrollable(
                new UiSelector().scrollable(true));
        deckViews.setAsHorizontalList();
        UiObject sApp;
        try {
            sApp = deckViews
                    .getChildByText(
                            new UiSelector()
                                    .className(android.widget.TextView.class
                                            .getName()), "拨号");
            sApp.clickAndWaitForNewWindow();
        } catch (UiObjectNotFoundException e) {
            e.printStackTrace();
        }
        //getUiDevice().pressBack();
    }

    // 读取每一次的内存值
    public String memory(String packageName) {
        Process proc = null;
        StringBuffer sb = new StringBuffer();
        String line, Pss = null;
        try {
            proc = Runtime.getRuntime().exec("dumpsys meminfo " + packageName);
            proc.waitFor();
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    proc.getInputStream()));
            while ((line = br.readLine()) != null) {
                if (line.contains("TOTAL")) {
                    sb.append(line + "\n");
                }
            }
            String[] s = sb.toString().split("TOTAL");
            String s2 = s[1].trim();
            String[] s3 = s2.split("    ");
            Pss = s3[0].trim();
            System.out.println("***调试开始***");
            System.out.println(sb.toString());// 打印字符串
            System.out.println(Arrays.toString(s));// 打印数组
            System.out.println(s2);
            System.out.println(Arrays.toString(s3));
            System.out.println("Pss=" + Pss);
            System.out.println("***调试完成***");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return Pss;
    }

    // 格式化时间
    public String formatDate() {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHms");
        String time = sdf.format(date);
        return time;
    }

    // 创建文件保存日志
    public File mkFile(String casename) {
        String path = "/storage/sdcard0/uiautomator/memory";
        String file = path + "/Scene_"+casename + formatDate() + ".log";
        File filePath = new File(path);
        File txt = new File(file);
        if (!filePath.exists() && !txt.exists()) {
            filePath.mkdirs();
            try {
                txt.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return txt;
    }

}

2.用 bat脚本连续读取应用程序的内存使用情况(一边操作一边观察内存值是否一直上升)

set process=com.android.contacts
@adb shell dumpsys meminfo %process% | findstr "Pss"
:m
@adb shell dumpsys meminfo %process% | findstr "TOTAL"
@ping -n 5 127.1>nul
@goto m

3.用eclipse中的DDMS

手动连电脑,选中要测试的进程名--点击Update help--操作应用的同时观察右边Heap区域的total size是否会一直上升,在此期间可以点击GC按扭触发android垃圾回收

如果一直呈上升趋势则点击Dump HPROF按扭把内存映像拷贝下来,然后用MAT工具去分析。

时间: 2024-10-30 19:07:12

android内存泄漏测试的相关文章

android内存泄漏系列- 分析hprof文件

转载请注明出处 http://www.cnblogs.com/weiwangnuanyang/p/5703702.html ,谢谢. 如果只是想确定一下某一个场景是否有内存泄漏,AndroidStadio的控制台就有一个好工具,反复操作观察曲线是否上扬,如果曲线上扬则说明内存泄漏 但是,上面的工具不够强大,不能看出内存中驻留的具体的类和类的引用关系. 下面就来重点介绍一下,解决android内存泄漏必备利器-Memory Analysis; 具体安装方式请移步度娘. 我们这里重点介绍如何利用Me

Android内存泄漏的各种原因详解

转:http://mobile.51cto.com/abased-406286.htm 1.资源对象没关闭造成的内存泄漏 描述: 资源性对象比如(Cursor,File文件等)往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们,以便它们的缓冲及时回收内存.它们的缓冲不仅存在于 java虚拟机内,还存在于java虚拟机外.如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄漏.因为有些资源性对象,比如 SQLiteCursor(在析构函数finalize(),如果我们没有关

Android内存泄漏查找和解决

Android内存泄漏查找和解决 目录: 内存泄漏的概念 一个内存泄漏的例子 Java中"失效"的private修饰符 回头看内存泄漏例子泄漏的重点 强引用与弱引用 解决内部类的内存泄漏 Context造成的泄漏 使用LeakCanary工具查找内存泄漏 总结 一.内存泄漏概念 1.什么是内存泄漏? 用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元.直到程序结束.即所谓的内存泄漏. 其实说白了就是该内存空间使用完毕之后未回收 2.内存泄漏会导致的问题 内

android 内存泄漏分析技巧

java虚拟机运行一般都有一个内存界限,超过这个界限,就会报outofmemory.这个时候一般都是存在内存泄漏.解决内存泄漏问题,窃以为分为两个步骤:分析应用程序是否真的有内存泄漏,找到内存泄漏的地方.这两个步骤都不是一般意义上的调试,直接打log,断点调试都不是太给力.动脑筋想一想,内存问题应该在很多地方上都会出现,这么常见的问题应该是有工具的.android现在更可以说是一个生态系统,当然也有很多开发辅助工具.在前面的两个步骤中都有很强大的武器,熟练的掌握这些利器,分析问题就会事半功倍.

Android 内存泄漏总结

Java中的内存泄漏 java内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使用导致 GC 不能回收.在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是可达的,即在有向图中,存在通路可以与其相连:其次,这些对象是无用的,即程序以后不会再使用这些对象.如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存. 在C++中,内存泄漏的范围更大一些.有些对象被

Android内存泄漏

韩梦飞沙  韩亚飞  [email protected]  yue31313  han_meng_fei_sha #Android 内存泄漏总结 内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题.内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使用导致 GC 不能回收.最近自己阅读了大量相关的文档资料,打算做个 总结 沉淀下来跟大家一起分享和学习,也给自己一个警示,以后 coding 时怎么避免这些情况,提高应用的体验

Android 内存泄漏优化汇总

android内存泄漏优化摘要 博客分类: android android内存溢出OutOfMemoryError . android移动应用程序的内存分配一般是8凯瑟琳约,不正确地假定处理内存处理非常easy创建OutOfMemoryError.我们的产品是最常见的错误是OutOfMemoryError的异常, 在解决这个异常时在网上发现非常多关于OutOfMemoryError的原因的介绍. OutOfMemoryError主要由下面几种情况造成: 1.数据库的cursor没有关闭. 操作S

Qt 内存泄漏测试

在说Qt的内存测试之前,首先需要说明和肯定的一点是:Qt是绝对没有内存泄漏的,我们必须相信这一点. 接下来,说明一下基于Linux的Qt内存测试工具及其用法和说明: 一.内存测试工具Valgrind 安装就不具体说了,网上一堆堆的 二.用法: 安装完Valgrind之后,打开Qt Creator,打开我们的项目,然后在Qt Creator的菜单中的Analyse=>Valgrind Memory Analyse.注意,需要在Debug模式下才行. 三.Valgrind User Manual 具

android 内存泄漏检测工具 LeakCanary 泄漏金丝雀

韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha [email protected] 内存泄漏检测工具 android 内存泄漏检测工具 ======== 内存泄漏 就是  无用的对象没有被回收,占用着内存,使得可用内存变小了. 如何检测内存泄漏, 可以使用 LeakCanary来检测内存泄漏. leak  是 泄漏的意思.. Canary 是 金丝雀 的意思. 在运行 应用的时候, 泄漏金丝雀 如果检测到内存泄漏 会显示一个通知. ======== LeakCanary捕获