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 + "
").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 + "
").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 + "
").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 + "
").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 + "
").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 + "
").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 + "
").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 + "
").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 + "
").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 + "
");
                }
            }
            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 heap--操作应用的同时观察右边Heap区域的total size是否会一直上升,在此期间可以点击GC按扭触发android垃圾回收

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

上面这命令也可以获取HPROF文件

原文地址:https://www.cnblogs.com/penghong2014/p/4914787.html