日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

TraceView issue

發布時間:2024/8/1 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TraceView issue 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

使用traceview時,遇到一個這樣的問題:

Exception in thread "main" java.lang.RuntimeException: Method exit (android/widget/AbsListView.startScrollIfNeeded (I)Z) does not match current method (java/lang/Math.abs (I)I)

這個是google自己bug,貌似出現在android4.0-4.2之間,主要是在mips架構里面發現的,不過現在的最新版本已修復此bug。

如果不幸拿到的android源碼還存在這個bug,需要自己修復。

traceiew的工作原理是跟蹤函數的調用路徑,然后計算整條調用路徑或者單個函數的執行時間,進而測試系統或者應用程序的性能。實際上,traceiew只是在pc端運行的一個工具,它用來解析目標設備上生成的.trace文件。所以,traceview本身沒有問題,只是目標設備上生成的.trace文件有問題。目標設備上是使用profile生成.trace文件的。profile把函數的進入(entry)和退出(exit)都記錄在.trace文件中,記錄的存儲方式是按照棧(stack)的方式,所以traceiew解析.trace文件時也需要用棧的方式。

現在出現錯誤的原因是函數的進入(entry)和退出(exit)不配對,也就是說有些函數的進入或者退出沒有被記錄下來。這就需要跟蹤.trace文件是如何生成的。

詳細的過程就不螯述了,這里只說一下跟蹤的路徑吧,有興趣的朋友可以看下。經過的文件有:

frameworks/base/cmds/am/src/com/android/commands/am/Am.java

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

frameworks/base/core/java/android/app/ActivityThread.java

frameworks/base/core/java/android/os/Debug.java

libcore/dalvik/src/main/java/dalvik/system/VMDebug.java

dalvik/vm/native/dalvik_system_VMDebug.cpp

dalvik/vm/Profile.cpp

.trace最主要的生成過程是在dalvik/vm/Profile.cpp中,后來發現最可能出錯的地方是,其中只有一個記錄函數進入的地方,然而卻有兩個記錄退出的地方。所以有可能是退出時使用了錯誤的函數。

記錄進入的函數:

dvmFastMethodTraceEnter

記錄退出的兩個函數:

dvmFastNativeMethodTraceExit

dvmFastMethodTraceExit

這些函數是在匯編代碼里邊調用的,涉及到匯編代碼就是架構相關了。android支持的架構有ARM,MIPS和X86。既然是在MIPS發現了這個問題,所以就看MIPS架構相關的代碼,后來發現在:

dalvik/vm/mterp/mips/OP_EXECUTE_INLINE.S

dalvik/vm/mterp/mips/OP_EXECUTE_INLINE_RANGE.S

dalvik/vm/mterp/out/InterpAsm-mips.S

這三個文件里面都調用了上面的函數。第三個文件是由很多.S文件(包括第一和第二個文件)生成的,可以忽視。所以調查前兩個文件。

OP_EXECUTE_INLINE.S里調用的代碼片段:

.L${opcode}_debugmode:move a0, rBIXJAL(dvmResolveInlineNative)beqz v0, .L${opcode}_resume # did it resolve? no, just move onmove rOBJ, v0 # remember methodmove a0, v0move a1, rSELFJAL(dvmFastMethodTraceEnter) # (method, self)addu a1, rSELF, offThread_retval # a1<- &self->retvalGET_OPB(a0) # a0 <- B# Stack should have 16/20 availablesw a1, 16(sp) # push &self->retvalBAL(.L${opcode}_continue) # make call; will return afterlw gp, STACK_OFFSET_GP(sp) # restore gpmove rINST, v0 # save result of inlinemove a0, rOBJ # a0<- methodmove a1, rSELF # a1<- selfJAL(dvmFastMethodTraceExit) # (method, self)beqz v0, common_exceptionThrown # returned false, handle exceptionFETCH_ADVANCE_INST(3) # advance rPC, load rINSTGET_INST_OPCODE(t0) # extract opcode from rINSTGOTO_OPCODE(t0) # jump to next instruction

OP_EXECUTE_INLINE_RANGE.S里面的調用片段:

/** We're debugging or profiling.* rBIX: opIndex*/ .L${opcode}_debugmode:move a0, rBIXJAL(dvmResolveInlineNative)beqz v0, .L${opcode}_resume # did it resolve? no, just move onmove rOBJ, v0 # remember methodmove a0, v0move a1, rSELFJAL(dvmFastMethodTraceEnter) # (method, self)addu a1, rSELF, offThread_retval # a1<- &self->retvalGET_OPA(a0) # a0 <- A# Stack should have 16/20 availablesw a1, 16(sp) # push &self->retvalmove rINST, rOBJ # rINST<- methodBAL(.L${opcode}_continue) # make call; will return afterlw gp, STACK_OFFSET_GP(sp) # restore gpmove rOBJ, v0 # save result of inlinemove a0, rINST # a0<- methodmove a1, rSELF # a1<- selfJAL(dvmFastNativeMethodTraceExit) # (method, self)beqz rOBJ, common_exceptionThrown # returned false, handle exceptionFETCH_ADVANCE_INST(3) # advance rPC, load rINSTGET_INST_OPCODE(t0) # extract opcode from rINSTGOTO_OPCODE(t0) # jump to next instruction

其中,OP_EXECUTE_INLINE.S調用的組合是:

dvmFastMethodTraceEnter

dvmFastMethodTraceExit

OP_EXECUTE_INLINE_RANGE.S調用的組合是:

dvmFastMethodTraceEnter

dvmFastNativeMethodTraceExit

但是,我發現OP_EXECUTE_INLINE.S里面的調用是不符合邏輯的。

請看:

move a0, rOBJ # a0<- methodmove a1, rSELF # a1<- selfJAL(dvmFastMethodTraceExit) # (method, self)這段代碼,程序準備了a0 和a1兩個參數,但是回頭看看dvmFastMethodTraceExit和dvmFastNativeMethodTraceExit的函數原型:

void dvmFastMethodTraceExit(Thread* self)

void dvmFastNativeMethodTraceExit(const Method* method, Thread* self)

很明顯,dvmFastMethodTraceExit只有一個參數,所以沒必要準備兩個參數。所以,這段代碼的編寫者原意應該是想要調用dvmFastNativeMethodTraceExit的。把OP_EXECUTE_INLINE.S里面的dvmFastMethodTraceExit換成dvmFastNativeMethodTraceExit,執行dalvik/vm/mterp/rebuild.sh重新生成dalvik/vm/mterp/out/InterpAsm-mips.S,然后重編dalvik,啟動運行,生成.trace文件,traceiew解析,成功了!

總結

以上是生活随笔為你收集整理的TraceView issue的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。