trace文件android
1. android 怎么解析tra文件
对于从事Android开发的人来说,遇到ANR(Application Not Responding)是比较常见的问题。一般情况下,如果有ANR发生,系统都会在/data/anr/目录下生成trace文件,通过分析trace文件,可以定位产生ANR的原因。产生ANR的原因有很多,比如CPU使用过高、事件没有得到及时的响应、死锁等,下面将通过一次因为死锁导致的ANR问题,来说明如何通过trace文件分析ANR问题。
对应的部分trace文件内容如下:
"PowerManagerService" prio=5 tid=24 MONITOR
| group="main" sCount=1 dsCount=0 obj=0x41dd0eb0 self=0x5241b218
| sysTid=567 nice=0 sched=0/0 cgrp=apps handle=1380038664
| state=S schedstat=( 6682116007 11324451214 33313 ) utm=450 stm=219 core=1
at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:~13045)
- waiting to lock <0x41a874a0> (a com.android.server.am.ActivityManagerService) held by tid=12 (android.server.ServerThread)
at android.app.ContextImpl.sendBroadcast(ContextImpl.java:1144)
at com.android.server.power.PowerManagerService$DisplayBlankerImpl.unblankAllDisplays(PowerManagerService.java:3442)
at com.android.server.power.DisplayPowerState$PhotonicMolator$1.run(DisplayPowerState.java:456)
at android.os.Handler.handleCallback(Handler.java:800)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:194)
at android.os.HandlerThread.run(HandlerThread.java:60)
"Binder_B" prio=5 tid=85 MONITOR
| group="main" sCount=1 dsCount=0 obj=0x42744770 self=0x58329e88
| sysTid=3700 nice=-20 sched=0/0 cgrp=apps handle=1471424616
| state=S schedstat=( 1663727513 2044643318 6806 ) utm=132 stm=34 core=1
at com.android.server.power.PowerManagerService$DisplayBlankerImpl.toString(PowerManagerService.java:~3449)
- waiting to lock <0x41a7e420> (a com.android.server.power.PowerManagerService$DisplayBlankerImpl) held by tid=24 (PowerManagerService)
at java.lang.StringBuilder.append(StringBuilder.java:202)
at com.android.server.power.PowerManagerService.mp(PowerManagerService.java:3052)
at android.os.Binder.mp(Binder.java:264)
at android.os.Binder.onTransact(Binder.java:236)
at android.os.IPowerManager$Stub.onTransact(IPowerManager.java:373)
at android.os.Binder.execTransact(Binder.java:351)
at dalvik.system.NativeStart.run(Native Method)
"android.server.ServerThread" prio=5 tid=12 MONITOR
| group="main" sCount=1 dsCount=0 obj=0x41a76178 self=0x507837a8
| sysTid=545 nice=-2 sched=0/0 cgrp=apps handle=1349936616
| state=S schedstat=( 15368096286 21707846934 69485 ) utm=1226 stm=310 core=0
at com.android.server.power.PowerManagerService.isScreenOnInternal(PowerManagerService.java:~2529)
- waiting to lock <0x41a7e2e8> (a java.lang.Object) held by tid=85 (Binder_B)
at com.android.server.power.PowerManagerService.isScreenOn(PowerManagerService.java:2522)
at com.android.server.wm.WindowManagerService.(WindowManagerService.java:7749)
at com.android.server.wm.WindowManagerService.setEventDispatching(WindowManagerService.java:7628)
at com.android.server.am.ActivityManagerService.updateEventDispatchingLocked(ActivityManagerService.java:8083)
at com.android.server.am.ActivityManagerService.wakingUp(ActivityManagerService.java:8077)
at com.android.server.power.Notifier.sendWakeUpBroadcast(Notifier.java:474)
at com.android.server.power.Notifier.sendNextBroadcast(Notifier.java:455)
at com.android.server.power.Notifier.access$700(Notifier.java:62)
at com.android.server.power.Notifier$NotifierHandler.handleMessage(Notifier.java:600)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:194)
at com.android.server.ServerThread.run(SystemServer.java:1328)
从trace文件看,是因为TID为24的线程等待一个TID为12的线程持有的锁,TID为12的线程等待一个TID为85的线程持有的锁,而TID为85的线程确等待一个TID为24的线程持有的锁,导致了循环等待的现象,对应的trace文件的语句如下:
TID 24:- waiting to lock <0x41a874a0> (a com.android.server.am.ActivityManagerService) held by tid=12 (android.server.ServerThread)
TID 12: - waiting to lock <0x41a7e2e8> (a java.lang.Object) held by tid=85 (Binder_B)
TID 85:- waiting to lock <0x41a7e420> (a com.android.server.power.PowerManagerService$DisplayBlankerImpl) held by tid=24 (PowerManagerService)
既然是死锁,那么先看各线程都有那些锁。
先看TID=24的线程的栈顶,ActivityManagerService的broadcastIntent函数代码如下:
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String requiredPermission, boolean serialized, boolean sticky, int userId) {
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this) {
intent = verifyBroadcastLocked(intent);
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo,
resultCode, resultData, map, requiredPermission, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
可以看到TID=24需要ActivityManagerService这个锁。再看TID=12线程的栈顶,PowerManagerService的isScreenOnInternal函数代码如下:
private boolean isScreenOnInternal() {
synchronized (mLock) {
return !mSystemReady
|| mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF;
}
}
可以看到需要PowerManagerService的mlock这个锁。最后看TID=85线程的栈顶,同样在PowerManagerService里面,内部类DisplayBlankerImpl的toString函数:
public String toString() {
synchronized (this) {
return "blanked=" + mBlanked;
}
}
这是在内部类DisplayBlankerImpl里面实现的,所以需要DisplayBlankerImpl这个锁。
对应的表格如下:
表一 各线程等待的锁情况
从表一来看,没有出现死锁现象,似乎并不是我们所想的那样。难道不是死锁?开始有点小怀疑自己了,难道别的原因导致的。也许只看调用堆栈的顶端可能不行,栈顶只能看出各线程需要的锁,不能仅看自己要什么吧!一味索取可不好!人不是这样做的!看一下整个的堆栈调用流程,看看自己拥有了那些锁。
跟踪TID=24线程的堆栈,在PowerManagerService内部类DisplayBlankerImpl的unblankAllDisplays函数中持有锁:
public void unblankAllDisplays() {
synchronized (this) {
nativeSetAutoSuspend(false);
nativeSetInteractive(true);
mDisplayManagerService.();
mBlanked = false;
///M: add for tvout and hdmi
mTvOut.tvoutPowerEnable(true);
mHDMI.hdmiPowerEnable(true);
///@}
if (DEBUG) {
Slog.d(TAG_P, "unblankAllDisplays out ...");
}
if (mBootCompleted) {
Intent intent = new Intent(ACTION_LOCK_SCREEN_SHOW);
mContext.sendBroadcast(intent);
}
}
}
最后发送广播的代码,是我们自己添加的。根据unblankAllDisplays函数和broadcastIntent函数,可以看到TID=24的线程此时持有了DisplayBlankerImpl锁(unblankAllDisplays),等待ActivityManagerService锁(broadcastIntent)释放。
同样,跟踪TID=12线程的堆栈,在ActivityManagerService的wake_up函数中持有锁:
public void wakingUp() {
if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires permission "
+ android.Manifest.permission.DEVICE_POWER);
}
synchronized(this) {
Slog.i(TAG, "wakingUp");
mWentToSleep = false;
updateEventDispatchingLocked();
comeOutOfSleepIfNeededLocked();
}
}
根据wakingUp函数和isScreenOnInternal函数,可以看到TID=12的线程持有ActivityManagerService锁(wakingUp),等待PowerManagerService.mLock锁(isScreenOnInternal)。到这,似乎看到了希望,迷雾要拨开了,有点小自信是死锁导致的,但还不能最终下结论。
一鼓作气,跟踪TID=85线程的堆栈,在PowerManagerService的mp有持有锁的操作:
protected void mp(FileDescriptor fd, PrintWriter pw, String[] args) {
....
synchronized (mLock) {
...
}
根据toString函数和mp函数,可以看到TID=85线程此时持有PowerManagerService.mLock锁(mp),需要DisplayBlankerImpl(toString)。
2. 跟踪的trace文件,需要用什么工具回放
Traceview的使用步骤
分为以下三步:
1. 选择追踪范围加入记录代码
2.利用tools下的工具trace view打开.trace文件
3.分析trace文件
1. 选择追踪范围加入记录代码
首先,必须在程序当中加入代码,以便生成trace文件,有了这个trace文件才可以将其转化为图形。
要添加的代码如下:
1 Debug.startMethodTracing(“wirelessqa”); //开始
2 Debug.stopMethodTracing(); //结束
其中参数wirelessqa是要创建的trace文件的名称,wirelessqa.trace。默认路径是/sdcard/wirelessqa.trace,也可以自己制定/data/log/wirelessqa,表示文件在/data/log/wirelessqa.trace。
实例代码参考:
01 publicclass MainActivity extends Activity {
02
03 @Override
04 protectedvoid onCreate(Bundle savedInstanceState) {
05 super.onCreate(savedInstanceState);
06 setContentView(R.layout.activity_main);
07 setTitle(this.getClass().getName());
08 View toLoginView = findViewById(R.id.to_login);
09 // 开始记录 sdcard/wirelessqa.trace文件
10 Debug.startMethodTracing("wirelessqa");
11 toLoginView.setOnClickListener(new View.OnClickListener() {
12
13 publicvoid onClick(View view) {
14 Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
15 startActivity(intent);
16 }
17 });
18 }
19
20 @Override
21 protectedvoid onStop() {
22 super.onStop();
23 Debug.stopMethodTracing();// 结束记录wirelessqa.trace
24 }
25 }
说明:
开发文档中说可以在activity的onCreate()中添加Debug.startMethodTracing(), 而在onDestroy()中添加Debug.stopMethodTracing(),但是在实际的测试时发现这种方式其实并不好用,因为通常情况下我们的activity的onDestroy()是由系统决定何时调用的,因此可能等了很长时间都不会得到这个trace文件。
因此决定在onStop()中来调用Debug.stopMethodTracing()。这样当我们切换到其它activity或者点击home键的时候onStop()就会被调用,我们也就可以得到完整的trace file。
别忘了加入访问SD卡的权限
1 <uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
2 <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
2.利用tools下的工具trace view打开.trace文件
3. 分析trace文件
3. 如何分析trace文件
Oracle-trace文件分析
如果一个系统的执行效率比较低,一个比较好的方法是通过跟踪用户的会话并且使用tkprof工具使用排序功能格式化输出,从而找出有问题的sql语句。
例如首先从os上利用top命令找到当前占用cpu资源最高的一个进程的PID号9999;
然后在数据库中根据PID号找到相应的sid和serial#
select s.sid,s.serial# from v$session s,v$process p where s.paddr=p.addr and p.spid='9999';
然后通过exec dbms_monitor.session_trace_enable(sid,serial#)开启trace;
最后利用tkprof察看trace输出。
开启Trace文件输出
可以通过以下方法开启Trace文件输出(需要ALTER SESSION系统权限):
1) alter session/system set sql_trace=true
2) exec dbms_monitor.session_trace_enable/dbms_monitor.database_trace_enable
3) alter session set events '10046 trace name context forever, level 12'
Trace文件的位置
4. 求教,如何抓取Android trace log
您好,很高兴为您解答。1,安装SDK(参考androidsdk环境安装)2,使用数据线链接手机,在手机助手的sdcard中建立一个1.log的文件3,程序运行cmd4,输入抓取命令:logcat-s'*:E'>/mmt/sdcard/1.log5,使用手机崩溃一次6,查看日志抓取文件,分不清楚是那个时间段所造成的后果7,加入命令:-vtime就会显示出时间8,输入命令logcat-vtime-s'*:E'>/mmt/sdcard/1.log9,查看结果如若满意,请点击右侧【采纳答案】,如若还有问题,请点击【追问】希望我的回答对您有所帮助,望采纳!~O(∩_∩)O~
5. Android ANR trace 报告怎么看
后缀名是什么是.txt吗?Log分析你还可以去data/anr的目录下把trace.txt这个文件拷贝出来,在该文件中会写了产生anr的函数堆栈可以帮助分析
6. android trace 文件怎么分析
对于从事Android开发的人来说,遇到ANR(Application Not Responding)是比较常见的问题。一般情况下,如果有ANR发生,系统都会在/data/anr/目录下生成trace文件,通过分析trace文件,可以定位产生ANR的原因。产生ANR的原因有很多,比如CPU使用过高、事件没有得到及时的响应、死锁等,下面将通过一次因为死锁导致的ANR问题,来说明如何通过trace文件分析ANR问题。
对应的部分trace文件内容如下:
"PowerManagerService" prio=5 tid=24 MONITOR
| group="main" sCount=1 dsCount=0 obj=0x41dd0eb0 self=0x5241b218
| sysTid=567 nice=0 sched=0/0 cgrp=apps handle=1380038664
| state=S schedstat=( 6682116007 11324451214 33313 ) utm=450 stm=219 core=1
at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.Java:~13045)
- waiting to lock <0x41a874a0> (a com.android.server.am.ActivityManagerService) held by tid=12 (android.server.ServerThread)
at android.app.ContextImpl.sendBroadcast(ContextImpl.java:1144)
at com.android.server.power.PowerManagerService$DisplayBlankerImpl.unblankAllDisplays(PowerManagerService.java:3442)
at com.android.server.power.DisplayPowerState$PhotonicMolator$1.run(DisplayPowerState.java:456)
at android.os.Handler.handleCallback(Handler.java:800)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:194)
at android.os.HandlerThread.run(HandlerThread.java:60)
"Binder_B" prio=5 tid=85 MONITOR
| group="main" sCount=1 dsCount=0 obj=0x42744770 self=0x58329e88
| sysTid=3700 nice=-20 sched=0/0 cgrp=apps handle=1471424616
| state=S schedstat=( 1663727513 2044643318 6806 ) utm=132 stm=34 core=1
at com.android.server.power.PowerManagerService$DisplayBlankerImpl.toString(PowerManagerService.java:~3449)
- waiting to lock <0x41a7e420> (a com.android.server.power.PowerManagerService$DisplayBlankerImpl) held by tid=24 (PowerManagerService)
at java.lang.StringBuilder.append(StringBuilder.java:202)
at com.android.server.power.PowerManagerService.mp(PowerManagerService.java:3052)
at android.os.Binder.mp(Binder.java:264)
at android.os.Binder.onTransact(Binder.java:236)
at android.os.IPowerManager$Stub.onTransact(IPowerManager.java:373)
at android.os.Binder.execTransact(Binder.java:351)
at dalvik.system.NativeStart.run(Native Method)
"android.server.ServerThread" prio=5 tid=12 MONITOR
| group="main" sCount=1 dsCount=0 obj=0x41a76178 self=0x507837a8
| sysTid=545 nice=-2 sched=0/0 cgrp=apps handle=1349936616
| state=S schedstat=( 15368096286 21707846934 69485 ) utm=1226 stm=310 core=0
at com.android.server.power.PowerManagerService.isScreenOnInternal(PowerManagerService.java:~2529)
- waiting to lock <0x41a7e2e8> (a java.lang.Object) held by tid=85 (Binder_B)
at com.android.server.power.PowerManagerService.isScreenOn(PowerManagerService.java:2522)
at com.android.server.wm.WindowManagerService.(WindowManagerService.java:7749)
at com.android.server.wm.WindowManagerService.setEventDispatching(WindowManagerService.java:7628)
at com.android.server.am.ActivityManagerService.updateEventDispatchingLocked(ActivityManagerService.java:8083)
at com.android.server.am.ActivityManagerService.wakingUp(ActivityManagerService.java:8077)
at com.android.server.power.Notifier.sendWakeUpBroadcast(Notifier.java:474)
at com.android.server.power.Notifier.sendNextBroadcast(Notifier.java:455)
at com.android.server.power.Notifier.access$700(Notifier.java:62)
at com.android.server.power.Notifier$NotifierHandler.handleMessage(Notifier.java:600)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:194)
at com.android.server.ServerThread.run(SystemServer.java:1328)
从trace文件看,是因为TID为24的线程等待一个TID为12的线程持有的锁,TID为12的线程等待一个TID为85的线程持有的锁,而TID为85的线程确等待一个TID为24的线程持有的锁,导致了循环等待的现象,对应的trace文件的语句如下:
TID 24:- waiting to lock <0x41a874a0> (a com.android.server.am.ActivityManagerService) held by tid=12 (android.server.ServerThread)
TID 12: - waiting to lock <0x41a7e2e8> (a java.lang.Object) held by tid=85 (Binder_B)
TID 85:- waiting to lock <0x41a7e420> (a com.android.server.power.PowerManagerService$DisplayBlankerImpl) held by tid=24 (PowerManagerService)
7. android怎么使用rpmbuild
对于从事Android开发的人来说,遇到ANR(Application Not Responding)是比较常见的问题。一般情况下,如果有ANR发生,系统都会在/data/anr/目录下生成trace文件,通过分析trace文件,可以定位产生ANR的原因。产生ANR的原因有很多,比如CPU使用过高、事件没有得到及时的响应、死锁等,下面将通过一次因为死锁导致的ANR问题,来说明如何通过trace文件分析ANR问题。
对应的部分trace文件内容如下:
"PowerManagerService" prio=5 tid=24 MONITOR
| group="main" sCount=1 dsCount=0 obj=0x41dd0eb0 self=0x5241b218
| sysTid=567 nice=0 sched=0/0 cgrp=apps handle=1380038664
| state=S schedstat=( 6682116007 11324451214 33313 ) utm=450 stm=219 core=1
at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:~13045)
- waiting to lock <0x41a874a0> (a com.android.server.am.ActivityManagerService) held by tid=12 (android.server.ServerThread)
8. android traceview在哪
1.假定采用Debug.startMethodTracing和Debug.stopMethodTracing方式录制了trace文件。如本经验中的abc.trace文件
2.启动cmd。进入到trace文件所在的目录。
执行traceview trace文件。如图,traceview E:\\abc.trace
3.在traceviwe工具中,上面的Panel是timeline Panel,如图的例子:
4.在traceviwe工具中,下面的panel是性能分析的panel,如图的例子:
5.还可以使用dmtracemp工具生成性能图
9. android trace文件怎么看
后缀名是什么 是.txt吗?
Log分析 你还可以去data/anr的目录下把trace.txt这个文件拷贝出来,在该文件中会写了产生anr的函数堆栈可以帮助分析
10. 如何对Android的本地代码进行profiling
现在用Android native code写程序库的人越来越多。对于那些需要写的库实时性要求特别强的应用,通过profiling来进行优化是一个非常有用的特性,因为它能帮你理解程序编译后的本质,比如多少instruction,哪些method调用多少次,多长时间,等等。
Android开发环境提供了Traceview这样一个工具,可以点到这个链接里面去看官方对他的介绍。总的来说,就是它提供给程序开发者目标程序的执行日志,以此帮助你调试程序和优化性能。有两种方法能够声称traceview所需的log,一种是利用DDMS的profiling特性,通过控制什么时候开始和结束logging来获得log。这个方法在你没有程序源代码的时候有用,因为只需要Run程序就能获得log信息,但是没有精准的起始中止控制。另一种是通过将Android自带的Debug类加到code中,然后调用里面的method来开始和中止trace信息的纪录。这个方法能让开发者非常精准地控制什么时候开始纪录,什么时候结束纪录,因为开始和技术都是在code中执行的。
对于Java程序来说,官方网页介绍了一个标准流程,就是在程序中引入Debug类,然后在你想要开始纪录profiling信息的时候调用startMethodTracing(),然后在准备结束的时候调用stopMethodTracing()方法。纪录的log文件默认放在sdcard中。
然而对于本地native代码,该方法就无效了。原因是这个方式只能trace你的java层的方法和其对Android API的调用,却无法trace Android API背后的那些方法,也无法trace你自己写的native code。如果你希望trace这些更底层的代码,就需要用Debug类提供的Debug.startNativeTracing()和 Debug.stopNativeTracing()。而且,这个配对只能工作的虚拟机emulator中,因为只有trace qemu emulator,才能去trace每一个进程的每一条cpu指令,甚至包括内核的代码,我们也才能获得更多的信息比如context switch,cache misses。
下面就来看看,利用该方法对来profile native code是怎样一个流程:
1. 新建一个Android Virtual Device,给一个名字,比如Profile。可以在AVD manager中创建。
2. 在命令行中通过命令”emulator -avd -trace
” 来运行该AVD。比如emulator -avd Profile -trace myTrace。
3. 将startNativeTracing()和stopNativeTracing()添加到你想profile的代码中。
4. 在Eclipse中build代码,确保没有错误。安装到正在运行的AVD中。
5. 去AVD中运行代码,确保你希望trace的代码段正常运行了。如果你观察运行AVD的那个terminal的窗口,应该会有比如“–start tracing–” 和 “–stop tracing–”这样的消息出现,这就说明代码正常运行了。
6. App运行完毕后,退出emulator。
7. 去你的用户目录找trace文件。这个目录是存储你AVD settings的目录,默认一般都在/Home/User/.android/avd/下。这个User是你自己的用户名,如果你是用的Mac或者Linux,这个路径也就是~/.android/avd。
8. 找到和你AVD名字对应的文件夹,里面有另一个子文件夹,命名就是你的trace名字,比如这里就是myTrace。里面的文件包括:
qtrace.bb
qtrace.exc
qtrace.insn
qtrace.method
qtrace.pid
qtrace.static
9.你需要用tracedmmp这个工具来将这些文件转化为符合Traceview格式的文件。问题在于,坑爹的Android SDK/NDK环境不原生提供这个工具。所以……..请看下一步
10. 好吧,这个工具来自于Android的源代码环境。那我们需要做的,就是下载整个Android源代码,编译。这个过程通常会持续……一个小时以上。请参考官方手册来进行编译。如果你使用的是Linux,恭喜你,什么别的资料都不用找,就一步一步按照手册来就行了。如果你是Mac用户……哥们,还是按照官方手册来吧,但过程就听天由命了。
11. Okay,假设到这里,你已经完成了整个Android源代码的编译。接下来,在源代码的根目录下运行“source build/envsetup.sh”,然后将根目录下的/out/host/xxxx/bin加到PARH路径中。xxx表示你的编译平台。这下你就可以run tracedmmp了。开一个终端,执行“tracedmmp ~/.android/avd/Profile/myTrace/”,tracedmmp去分析刚才那些五花八门的二进制文件,挖掘里面的symbolic信息,然后将其和trace数据对应。等一小会,就可以得到instruction的信息,并会生成一个更详细的包括所有profiling信息的html文档,这个文档和Traceview兼容的,可以直接打开,也可以用Traceview工具分析。
这样,整个profiling过程就结束了。
需要注意一点的是,这个方法和method tracing比有一个局限,就是因为工作在真实设备上,所以emulator不能模拟所有的真实设备效果,比如memory contention和bus contention,同时也无法模拟真实的cache效果,因为emulator中的cache设计是大大简化了的。
