您的位置:首页 > 移动开发 > Android开发

android内存泄漏测试

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

测试方法:

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工具去分析。



上面这命令也可以获取HPROF文件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: