安卓手机run in和monkey in the jungle测试时干什么用的

[原创]Android 自动化测试Monkey、Monkeyrunner
软件测试是软件产品开发过程中的重要环节,对于保重软件质量具有重要的意思。手动测试和自动化测试是软件测试的两个基本手段。本文主要介Android&–&自动化测试
Android平台上提供了一些自动化测试工具:Monkey、Monkeyrunner。
Monkey、Monkeyrunner&概述
一、Monkey&概述
monkey可以直接在XP/WIN7上运行,只要XP/WIN7上能用adb,即可使用。
Monkey测试是Android平台自动化测试的一种手段,通过Monkey程序模拟用户触摸屏幕、滑动Trackball、按键等操作来对设备上的程序进行压力测试,检测程序多久的时间会发生异常,Monkey测试是一种为了测试软件的稳定性、健壮性的快速有效的方法。
Monkey程序由Android系统自带,使用Java语言写成,在Android文件系统中的存放路径是:/system/framework/monkey.jar。
Monkey.jar程序是由一个名为“monkey”的Shell脚本来启动执行,shell脚本在Android文件系统中的存放路径是:/system/bin/monkey;这样就可以通过在shell窗口中执行:&adb&shell&monkey&{+命令参数}来进行Monkey测试了。
二、Monkeyrunner&概述
1、monkeyrunner工具提供了一个API,使用此API写出的程序可以在Android代码之外控制Android设备和模拟器。通过monkeyrunner,您可以写出一个Python程序去安装一个Android应用程序或测试包,运行它,向它发送模拟击键,截取它的用户界面图片,并将截图存储于工作站上。
monkeyrunner工具的主要设计目的是用于测试功能/框架水平上的应用程序和设备,或用于运行单元测试套件,但您当然也可以将其用于其它目的
Monkeyrunner文件在SDK目录的tools子目录下,运行时,如果没有指定环境变量,需到tools目录下方可执行
Monkeyrunner支持自己编写插件,控制事件,随时截图,简而言之,任何你在模拟器/设备中能干的事情,MonkeyRunner都能干,而且还可以记录和回放!!!&
2、monkeyrunner工具为Android测试提供了以下特性:
多设备控制:monkeyrunner&API可以跨多个设备或模拟器实施测试套件。您可以在同一时间接上所有的设备或一次启动全部模拟器(或统统一起),依据程序依次连接到每一个,然后运行一个或多个测试。您也可以用程序启动一个配置好的模拟器,运行一个或多个测试,然后关闭模拟器。
功能测试:&monkeyrunner可以为一个应用自动贯彻一次功能测试。您提供按键或触摸事件的输入数值,然后观察输出结果的截屏。
回归测试:monkeyrunner可以运行某个应用,并将其结果截屏与既定已知正确的结果截屏相比较,以此测试应用的稳定性。
可扩展的自动化:由于monkeyrunner是一个API工具包,您可以基于Python模块和程序开发一整套系统,以此来控制Android设备。除了使用monkeyrunner&API之外,您还可以使用标准的Python&os和subpress模块来调用如adb这样的Android工具。
三、Monkey和Monkeyrunner工具区别
Monkey:Monkey工具直接运行在设备或模拟器的adb shell中,生成用户或系统的伪随机事件流。
monkeyrunner:monkeyrunner工具则是在工作站上通过API定义的特定命令和事件控制设备或模拟器。
Monkey&的基本使用方法
1、可以通过开发机器上的命令行或脚本来启动Monkey。
由于Monkey运行在模拟器/设备环境中,所以必须用其环境中的shell来进行启动。可以通过在每条命令前加上adb&shell来达到目的,也可以进入Shell后直接输入Monkey命令。基本语法如下:
&&adb&shell&monkey&[options]&
&adb&shell
如果不指定options,Monkey将以无反馈模式启动,并把事件任意发送到安装在目标环境中的全部包。下面是一个更为典型的命令行示例,它启动指定的应用程序,把调试等级加了1,并向其发送500个伪随机事件:
&&adb&shell&monkey&-p&your.package.name&–v&5002、Monkey&命令可简单分为如下四类:
基本配置选项:&&如设置尝试的事件数量,反馈信息的级别。
运行约束选项:&如设置只对单独的一个包进行测试。
事件类型和频率:&如设置触摸屏事件的发生频率。
调试选项,如设置忽略应用程序异常,继续向系统发送事件,直到计数完成
3、Monkey 命令解析:
Monkey&runner&的基本使用方法:
1、Monkeyrunner&环境搭建
2、下载安装Python
下载网址:https://www.python.org/
3、环境变量配置&&&;C:\Python27(安装目录复制到Path的后面,注前面的“;”不要忘记哦)环境变量路径以Win7为例:计算机&-&&属性&-&&高级系统设置&-&&环境变量&-&&系统变量&-&&找到Path
4、monkeyrunnerAPI于com.android.monkeyrunner包中包含三个模块:
MonkeyRunner
:一个为monkeyrunner程序提供工具方法的类。这个类提供了用于连接monkeyrunner至设备或模拟器的方法。它还提供了用于创建一个monkeyrunner程序的用户界面以及显示内置帮助的方法。
waitForConnection&(float&timeout,&string&deviceId)&
sleep&(float&seconds)&
help&(string&format)&
MonkeyImage
:表示一个截图对象。这个类提供了截图、将位图转换成各种格式、比较两个MonkeyImage对象以及写图像到文件的方法。
MonkeyImage创建对象的方法如下:
newimage&=MonkeyDevice.takeSnapshot()
writeToFile&(string&path,&string&format)
MonkeyDevice
:表示一个设备或模拟器。这个类提供了安装和卸载程序包、启动一个活动以及发送键盘或触摸事件到应用程序的方法。您也可以用这个类来运行测试包。
MonkeyDevice的常用方法:
a.Touch&(x坐标,&y坐标,动作)
可以通过开启Pointer&location在手机上直接查看坐标点.
b.Press(‘按键值’,&动作)
动作包括:DOWN,&UP,&DOWN_AND_UP。大部分时间用DOWN_AND_UP来模拟按键、松手的过程。比如要进行一个返回键操作:
device.press('KEYCODE_BACK',MonkeyDevice.DOWN_AND_UP)
c.Drag((x,&y),(x,&y),持续时间,轨迹点)
按键值为Andriod键值表中有的值drag((x,&y),(x,&y),持续时间,轨迹点)
第一组是起始坐标,第二组终点坐标。这里的坐标值要通过hierarchyviewer工具来获取,轨迹点类似采样
d.启动Activity:startActivity(‘string’)
在python程序中,您将以Python模块的形式使用这些类。monkeyrunner工具不会自动导入这些模块。您必须使用类似如下的from语句:
from&&com.android.monkeyrunner&&import&&Monkey&Runner,&&&&&
Monkey&Device,&Monkey&Image
您可以在一个from语句中导入超过一个模块,其间以逗号分隔。
5、运行monkeyrunner
monkeyrunner命令的语法为:
monkeyrunner&-plugin
&程序文件名&&&程序选项&
1、启动一个Android系统的模拟器,即为命令中device
2、&将cmd命令定位到android&SDK的路径下的tools目录
3、输入命令"monkeyrunner",回车,进入Shell命令交互方式
&&&&导入monkeyrunner所要使用的模块:&&&&&&&&A.直接在shell命令中输入(然后回车):
&&&&from&com.android.monkeyrunner&import&MonkeyRunner,&
&&&&MonkeyDevice,MonkeyImage
&&&&B.输入device&=&MonkeyRunner.waitForConnection(),然后回车
6、一个简单的monkeyrunner程序实例
以下为一个简单的monkeyrunner程序,它将会连接到一个设备,创建一个MonkeyDevice对象。使用MonkeyDevice对象,程序将安装一个Android应用包,运行其中一个活动,并向其发送按键事件。程序接下来会将结果截图,创建一个MonkeyImage对象,并使用这个对象截图将保存至.png文件。
# 导入此程序所需的monkeyrunner模块
from&com.android.monkeyrunner&import&MonkeyRunner,&MonkeyDevice MonkeyImage
# 连接当前设备,返回一个MonkeyDevice对象
device&=&MonkeyRunner.waitForConnection()
# 安装Android包,注意,此方法返回的返回值为boolean,由此您可以判断安装过程是否正常
device.installPackage('myproject/bin/MyApplication.apk')
# 运行此应用中的一个活动device.startActivity(component='com.example.android.myapplication.MainActivity')
# 按下菜单按键
device.press('KEYCODE_MENU','DOWN_AND_UP')
# 截取屏幕截图
result&=&device.takeSnapshot()
# 将截图保存至文件
result.writeToFile('myproject/shot1.png','png')
#时延(秒):
MonkeyRunner.sleep(3)&
#滑动屏幕(Python脚本):
for&i&in&range(1,70):device.drag(start,end,0.1,10)&&
#触击屏幕:&
device.touch(94,34,'DOWN_AND_UP')&&
# 运行此应用中的一个活动device.startActivity(component='com.example.android.myapplication.MainActivity')
# 按下菜单按键
device.press('KEYCODE_MENU','DOWN_AND_UP')
# 截取屏幕截图
result&=&device.takeSnapshot()
# 将截图保存至文件
result.writeToFile('myproject/shot1.png','png')
7、Monkeyrunner自动化测试的记录和回放
MonkeyRunner工具中提供了记录与回放的功能,可以通过monkey_recorder.py和monkey_playback.py两个python文件来实现。此两个文件存放在:android源代码&-&&&monkeyrunner源代码&-&&scripts文件夹。
&a、启动模拟器或通过USB连接手机
&b、打开命令行提示符,并且定位到Tools文件下输入:
&&&&&&&&monkeyrunner&monkey_recorder.py&按下回车键
录制界面菜单介绍:
注意:导出的脚本要与monkey_recorder.py和monkey_playback.py&在同一目录下,即Tools文件夹下。
脚本回放需要使用另外一个脚本&monkeyplayback.py
执行步骤:
&a、启动模拟器或通过USB连接手机
&b、打开命令行提示符,并且定位到Tools文件下输入:
&&&&&&&&monkeyrunner&monkeyplayback.py&&“sound”
&&&&&&&&按下回车键附录:脚本
1、monkeyrecoder.py
#Usage:&monkeyrunner&monkeyrecorder.py&
#monkeyrecorder.py&
from&com.android.monkeyrunner&import&MonkeyRunner
from&com.android.monkeyrunner.recorder&import&MonkeyRecorder
device&=&MonkeyRunner.waitForConnection()
MonkeyRecorder.start(device)
2、monkeyplayback.py
import&sys
from&com.android.monkeyrunner&import&MonkeyRunner
CMD_MAP&=&{
&&&&"TOUCH":lambda&dev,arg:dev.touch(**arg),
&&&&"DRAG":lambda&dev,arg:dev.drag(**arg),
&&&&"PRESS":lambda&dev,arg:dev.press(**arg),
&&&&"TYPE":lambda&dev,arg:dev.type(**arg),
&&&&"WAIT":lambda&dev,arg:MonkeyRunner.sleep(**arg)
#&Process&a&single&file&for&the&specified&device.
def&process_file(fp,device):
&&&&for&line&in&fp:
&&&&&&&&(cmd,rest)&=&line.split("|")
&&&&&&&&try:
&&&&&&&&&&&&rest&=&eval(rest)
&&&&&&&&except:
&&&&&&&&&&&&print"unable&to&parse&options"
&&&&&&&&&&&&continue
&&&&&&&&if&cmd&not&in&CMD_MAP:
&&&&&&&&&&&&print"unknown&command:"&+&cmd
&&&&&&&&&&&&continue
&&&&&&&&CMD_MAP[cmd](device,rest)
def&main():
&&&&file&=&sys.argv[1]
&&&&fp&=&open(file,"r")
&&&&device&=&MonkeyRunner.waitForConnection()
&&&&process_file(fp,device)
&&&&fp.close();
if&__name__=="__main__":
&&&&main()
上传的附件:
(34.40kb,6次下载)
(18.48kb,6次下载)
(26.01kb,7次下载)
(29.10kb,7次下载)
(13.80kb,5次下载)
支付方式:
最新回复 (8)
好东西,支持一下
好东西,最近用uiaotumator的比较多了吧
支持,支持:-D
好帖子,赞一个。
rest = eval(rest)这一句将字符串rest转换为字典,但是字典是无序的,将其恢复为命令执行时,会导致参数错误。
1.请先关注公众号。
2.点击菜单"更多"。
3.选择获取下载码。博客分类:
文章都为原创,转载请注明出处,未经允许而盗用者追究法律责任。 很久之前写的了,留着有点浪费,共享之。编写者:李文栋P.S. OpenOffice粘贴过来后格式有些混乱。
//WindowManager所在的进程是system_server,进程号是127
I/WindowManager( 127): Input event dispatching timed out sending to com.example.anrdemo/com.example.anrdemo.ANRActivity
//system_server进程中的ActivityManagerService请求kernel向5033进程发送SIGNAL_QUIT请求
//你可以在shell中使用命令达到相同的目的:adb shell kill -3 5033
//和其他的Java虚拟机一样,SIGNAL_QUIT也是Dalvik内部支持的功能之一
I/Process ( 127): Sending signal. PID: 5033 SIG: 3
//5033进程的虚拟机实例接收到SIGNAL_QUIT信号后会将进程中各个线程的函数堆栈信息输出到traces.txt文件中
//发生ANR的进程正常情况下会第一个输出
I/dalvikvm( 5033): threadid=4: reacting to signal 3
I/dalvikvm( 5033): Wrote stack traces to '/data/anr/traces.txt'
... ...//另外还有其他一些进程
//随后会输出CPU使用情况
E/ActivityManager( 127): ANR in com.example.anrdemo (com.example.anrdemo/.ANRActivity)
//Reason表示导致ANR问题的直接原因
E/ActivityManager( 127): Reason: keyDispatchingTimedOut
E/ActivityManager( 127): Load: 3.85 / 3.41 / 3.16
//请注意ago,表示ANR发生之前的一段时间内的CPU使用率,并不是某一时刻的值
E/ActivityManager( 127): CPU usage from 26835ms to 3662ms ago with 99% awake:
E/ActivityManager( 127): 9.4% 98/mediaserver: 9.4% user + 0% kernel
E/ActivityManager( 127): 8.9% 127/system_server: 6.9% user + 2% kernel / faults: 1823 minor
E/ActivityManager( 127): +0% 5033/com.example.anrdemo: 0% user + 0% kernel
E/ActivityManager( 127): 39% TOTAL: 32% user + 6.1% kernel
//这里是later,表示ANR发生之后
E/ActivityManager( 127): CPU usage from 601ms to 1132ms later with 99% awake:
E/ActivityManager( 127): 10% 127/system_server: 1.7% user + 8.9% kernel / faults: 5 minor
E/ActivityManager( 127): 10% 163/InputDispatcher: 1.7% user + 8.9% kernel
E/ActivityManager( 127): 1.7% 127/system_server: 1.7% user + 0% kernel
E/ActivityManager( 127): 1.7% 135/SurfaceFlinger: 0% user + 1.7% kernel
E/ActivityManager( 127): 1.7% 2814/Binder Thread #: 1.7% user + 0% kernel
E/ActivityManager( 127): 37% TOTAL: 27% user + 9.2% kernel
final void appNotResponding(ProcessRecord app, ActivityRecord activity,
ActivityRecord parent, final String annotation) {
//firstPids和lastPids两个集合存放那些将会在traces中输出信息的进程的进程号
ArrayList&Integer& firstPids = new ArrayList&Integer&(5);
SparseArray&Boolean& lastPids = new SparseArray&Boolean&(20);
//mController是IActivityController接口的实例,是为Monkey测试程序预留的,默认为null
if (mController != null) {
long anrTime = SystemClock.uptimeMillis();
if (MONITOR_CPU_USAGE) {
updateCpuStatsNow(); //更新CPU使用率
synchronized (this) { //一些特定条件下会忽略ANR
if (mShuttingDown) {
Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
} else if (app.notResponding) {
Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
} else if (app.crashing) {
Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
//使用一个标志变量避免同一个应用在没有处理完时重复输出log
app.notResponding =
//①当前发生ANR的应用进程被第一个添加进firstPids集合中
firstPids.add(app.pid);
//②dumpStackTraces是输出traces文件的函数
File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids, null);
String cpuInfo =
if (MONITOR_CPU_USAGE) { //MONITOR_CPU_USAGE默认为true
updateCpuStatsNow(); //再次更新CPU信息
synchronized (mProcessStatsThread) {
//输出ANR发生前一段时间内的CPU使用率
cpuInfo = mProcessStats.printCurrentState(anrTime);
info.append(processStats.printCurrentLoad());
info.append(cpuInfo);
//输出ANR发生后一段时间内的CPU使用率
info.append(processStats.printCurrentState(anrTime));
//③将ANR信息同时输出到DropBox中
addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
cpuInfo, tracesFile, null);
//在Android4.0中可以设置是否不显示ANR提示对话框,如果设置的话就不会显示对话框,并且会杀掉ANR进程
boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
synchronized (this) {
if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
Process.killProcessQuiet(app.pid);
// 显示ANR提示对话框
Message msg = Message.obtain();
HashMap map = new HashMap();
msg.what = SHOW_NOT_RESPONDING_MSG;
map.put("app", app);
if (activity != null) {
map.put("activity", activity);
mHandler.sendMessage(msg);
public static File dumpStackTraces(boolean clearTraces, ArrayList&Integer& firstPids,
ProcessStats processStats, SparseArray&Boolean& lastPids, String[] nativeProcs) {
//系统属性“dalvik.vm.stack-trace-file”用来配置trace信息输出文件
String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
if (tracesPath == null || tracesPath.length() == 0) {
File tracesFile = new File(tracesPath);
File tracesDir = tracesFile.getParentFile();
if (!tracesDir.exists()) tracesFile.mkdirs();
//FileUtils.setPermissions是个很有用的函数,设置文件属性时经常会用到
FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1); // drwxrwxr-x
//clearTraces为true,会删除旧文件,创建新文件
if (clearTraces && tracesFile.exists()) tracesFile.delete();
tracesFile.createNewFile();
FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
} catch (IOException e) {
Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
//一个重载函数
dumpStackTraces(tracesPath, firstPids, processStats, lastPids, nativeProcs);
return tracesF
getpropdalvik.vm.stack-trace-file
setprop dalvik.vm.stack-trace-file /tmp/stack-traces.txt
private static void dumpStackTraces(String tracesPath, ArrayList&Integer& firstPids,
ProcessStats processStats, SparseArray&Boolean& lastPids, String[] nativeProcs) {
//使用FileObserver监听应用进程是否已经完成写入traces文件的操作
//Android在判断桌面壁纸文件是否设置完成时也是用的FileObserver,很有用的类
FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
public synchronized void onEvent(int event, String path) { notify(); }
//首先输出firstPids集合中指定的进程,这些也是对ANR问题来说最重要的进程
if (firstPids != null) {
int num = firstPids.size();
for (int i = 0; i & i++) {
synchronized (observer) {
//前面提到的SIGNAL_QUIT
Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
observer.wait(200);
&!-- Watchdog写完后注意补充章节号 --&
Slog.i(TAG, "DropBox Service");
ServiceManager.addService(Context.DROPBOX_SERVICE, //服务名称为“dropbox”
new DropBoxManagerService(context, new File("/data/system/dropbox")));
public voidadd(DropBoxManager.Entryentry)
publicboolean isTagEnabled(String tag)
publicsynchronized DropBoxManager.Entry getNextEntry(String tag, long millis)
//文件中输出的第一个进程的trace信息,正是发生ANR的演示程序
//开头显示进程号、ANR发生的时间点和进程名称
----- pid 9183 at
22:20:42 -----
Cmd line: com.example.anrdemo
DALVIK THREADS: //以下是各个线程的函数堆栈信息
//mutexes表示虚拟机实例中各种线程相关对象锁的value值
(mutexes: tll=0 tsl=0 tscl=0 ghl=0 hwl=0 hwll=0)
//依次是:线程名、线程优先级、线程创建时的序号、①线程当前状态
"main" prio=5 tid=1 TIMED_WAIT
//依次是:线程组名称、suspendCount、debugSuspendCount、线程的Java对象地址、线程的Native对象地址
| group="main" sCount=1 dsCount=0 obj=0x self=0xce68
//sysTid是线程号,主线程的线程号和进程号相同
| sysTid=9183 nice=0 sched=0/0 cgrp=default handle=-
| schedstat=(
at java.lang.VMThread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:1213)
at java.lang.Thread.sleep(Thread.java:1195)
at com.example.anrdemo.ANRActivity.makeANR(ANRActivity.java:44)
at com.example.anrdemo.ANRActivity.onClick(ANRActivity.java:38)
at android.view.View.performClick(View.java:2486)
at android.view.View$PerformClick.run(View.java:9130)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3703)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)
//②Binder线程是进程的线程池中用来处理binder请求的线程
"Binder Thread #2" prio=5 tid=8 NATIVE
| group="main" sCount=1 dsCount=0 obj=0x40750b90 self=0x1440b8
| sysTid=9190 nice=0 sched=0/0 cgrp=default handle=1476256
| schedstat=( 63135 4 )
at dalvik.system.NativeStart.run(Native Method)
"Binder Thread #1" prio=5 tid=7 NATIVE
| group="main" sCount=1 dsCount=0 obj=0x self=0x78d40
| sysTid=9189 nice=0 sched=0/0 cgrp=default handle=1308088
| schedstat=( 43212 10 )
at dalvik.system.NativeStart.run(Native Method)
//线程名称后面标识有daemon,说明这是个守护线程
"Compiler" daemon prio=5 tid=6 VMWAIT
| group="system" sCount=1 dsCount=0 obj=0x self=0x141e78
| sysTid=9188 nice=0 sched=0/0 cgrp=default handle=1506000
| schedstat=(
at dalvik.system.NativeStart.run(Native Method)
//JDWP线程是支持虚拟机调试的线程,不需要关心
"JDWP" daemon prio=5 tid=5 VMWAIT
| group="system" sCount=1 dsCount=0 obj=0x self=0x16c958
| sysTid=9187 nice=0 sched=0/0 cgrp=default handle=1510224
| schedstat=( 7617 7 )
at dalvik.system.NativeStart.run(Native Method)
//“Signal Catcher”负责接收和处理kernel发送的各种信号,例如SIGNAL_QUIT、SIGNAL_USR1等就是被该线程
//接收到,这个文件的内容就是由该线程负责输出的,可以看到它的状态是RUNNABLE,不过此线程也不需要关心
"Signal Catcher" daemon prio=5 tid=4 RUNNABLE
| group="system" sCount=0 dsCount=0 obj=0x self=0x150008
| sysTid=9186 nice=0 sched=0/0 cgrp=default handle=1501664
| schedstat=( 6621 9 )
at dalvik.system.NativeStart.run(Native Method)
"GC" daemon prio=5 tid=3 VMWAIT
| group="system" sCount=1 dsCount=0 obj=0x self=0x168010
| sysTid=9185 nice=0 sched=0/0 cgrp=default handle=1503184
| schedstat=( 1778 2 )
at dalvik.system.NativeStart.run(Native Method)
"HeapWorker" daemon prio=5 tid=2 VMWAIT
| group="system" sCount=1 dsCount=0 obj=0x self=0x16a080
| sysTid=9184 nice=0 sched=0/0 cgrp=default handle=550856
| schedstat=( 36669 15 )
at dalvik.system.NativeStart.run(Native Method)
----- end 9183 -----
----- pid 127 at
22:20:42 -----
Cmd line: system_server
//省略其他进程的信息
Thread.java中定义的状态
Thread.cpp中定义的状态
TERMINATED
RUNNING/RUNNABLE
TIMED_WAITING
TIMED_WAIT
INITIALIZING
&!-- 线程的ThreadGroup最好也写进去 --&
E/ActivityManager( 127): ANR in com.example.anrdemo (com.example.anrdemo/.ANRActivity)
E/ActivityManager( 127): Reason: keyDispatchingTimedOut
E/ActivityManager( 127): Load: 3.85 / 3.41 / 3.16 //? CPU平均负载
//②ANR发生之前的一段时间内的CPU使用率
E/ActivityManager( 127): CPU usage from 26835ms to 3662ms ago with 99% awake://③
E/ActivityManager( 127): 9.4% 98/mediaserver: 9.4% user + 0% kernel
E/ActivityManager( 127): 8.9% 127/system_server: 6.9% user + 2% kernel / faults: 1823 minor //⑤ minor或者major的页错误次数
E/ActivityManager( 127)://⑥+0% 5033/com.example.anrdemo: 0% user + 0% kernel
E/ActivityManager( 127): 39% TOTAL: 32% user + 6.1% kernel
//⑦ANR发生之后的一段时间内的CPU使用率
E/ActivityManager( 127): CPU usage from 601ms to 1132ms later with 99% awake:
E/ActivityManager( 127): 10% 127/system_server: 1.7% user + 8.9% kernel / faults: 5 minor
E/ActivityManager( 127): 10% 163/InputDispatcher: 1.7% user + 8.9% kernel
E/ActivityManager( 127): 1.7% 127/system_server: 1.7% user + 0% kernel
E/ActivityManager( 127): 1.7% 135/SurfaceFlinger: 0% user + 1.7% kernel
E/ActivityManager( 127): 1.7% 2814/Binder Thread #: 1.7% user + 0% kernel
E/ActivityManager( 127): 37% TOTAL: 27% user + 9.2% kernel
CPU使用率= (T – I) / T
//第一次使用成员变量mProcessStats采样
if (MONITOR_CPU_USAGE) {
updateCpuStatsNow();
//声明了一个局部变量,参数true表示包括线程信息
final ProcessStats processStats = new ProcessStats(true);
//将processStats作为实参传入,在dumpStackTraces中相隔500毫秒两次调用其update函数进行采样
File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
String cpuInfo = null;
if (MONITOR_CPU_USAGE) {
//因为在第一次调用后,可能由于输出trace信息等操作,中间执行了较长的时间,所以有第二次使用成员变量
//mProcessStats采样,尽量使得采样时间点靠后。
//此函数中要求连续两次采样时间间隔不少于5秒,所以一般不会执行第二次采样。一旦执行,就会出现两个采样
//时间点一个在ANR发生之前,另一个在其之后,或者两个时间点都在ANR发生之后的情况。
updateCpuStatsNow();
synchronized (mProcessStatsThread) {
//mProcessStats是成员变量,创建对象时传入的参数是false,所以不包括线程信息
//此处先输出ANR发生之前一段时间内的CPU使用率
cpuInfo = mProcessStats.printCurrentState(anrTime);
info.append(processStats.printCurrentLoad());
info.append(cpuInfo);
//processStats对象是在ANR发生后创建并采样的,所以输出的是ANR发生之后一段时间内的CPU使用率
info.append(processStats.printCurrentState(anrTime));
。一个文件第一次被读写时会有很多的
&!-- 求证一下 --&
浏览 60027
浏览: 358831 次
来自: 北京
summertime2013 写道最后一句话,为什么继续超过1 ...
真心牛人啊
最后一句话,为什么继续超过10秒没返回,又会引起第2种ANR? ...
楼主,求出书啊。求内容啊
读了您的几篇文章,找到了很多昨天上午向您请教问题的答案,受益匪 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'}

我要回帖

更多关于 monkeyscript runcmd 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信