TraceView issue

本文探讨了在使用traceview进行Android性能测试时遇到的异常问题,特别是关于在MIPS架构下生成的.trace文件中出现的函数调用不匹配情况。深入分析了问题的根源,并提供了通过修改汇编代码解决此问题的方法,最终成功生成正确的.trace文件并由traceview正确解析。

使用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, rBIX
    JAL(dvmResolveInlineNative)
    beqz      v0, .L${opcode}_resume       #  did it resolve? no, just move on
    move      rOBJ, v0                     #  remember method
    move      a0, v0
    move      a1, rSELF
    JAL(dvmFastMethodTraceEnter)           #  (method, self)
    addu      a1, rSELF, offThread_retval  #  a1<- &self->retval
    GET_OPB(a0)                            #  a0 <- B
    # Stack should have 16/20 available
    sw        a1, 16(sp)                   #  push &self->retval
    BAL(.L${opcode}_continue)              #  make call; will return after
    lw        gp, STACK_OFFSET_GP(sp)      #  restore gp
    move      rINST, v0                    #  save result of inline
    move      a0, rOBJ                     #  a0<- method
    move      a1, rSELF                    #  a1<- self
    JAL(dvmFastMethodTraceExit)            #  (method, self)
    beqz      v0, common_exceptionThrown   #  returned false, handle exception
    FETCH_ADVANCE_INST(3)                  #  advance rPC, load rINST
    GET_INST_OPCODE(t0)                    #  extract opcode from rINST
    GOTO_OPCODE(t0)                        #  jump to next instruction

OP_EXECUTE_INLINE_RANGE.S里面的调用片段:

/*
     * We're debugging or profiling.
     * rBIX: opIndex
     */
.L${opcode}_debugmode:
    move      a0, rBIX
    JAL(dvmResolveInlineNative)
    beqz      v0, .L${opcode}_resume       #  did it resolve? no, just move on
    move      rOBJ, v0                     #  remember method
    move      a0, v0
    move      a1, rSELF
    JAL(dvmFastMethodTraceEnter)           #  (method, self)
    addu      a1, rSELF, offThread_retval  #  a1<- &self->retval
    GET_OPA(a0)                            #  a0 <- A
    # Stack should have 16/20 available
    sw        a1, 16(sp)                   #  push &self->retval
    move      rINST, rOBJ                  #  rINST<- method
    BAL(.L${opcode}_continue)              #  make call; will return after
    lw        gp, STACK_OFFSET_GP(sp)      #  restore gp
    move      rOBJ, v0                     #  save result of inline
    move      a0, rINST                    #  a0<- method
    move      a1, rSELF                    #  a1<- self
    JAL(dvmFastNativeMethodTraceExit)      #  (method, self)
    beqz      rOBJ, common_exceptionThrown #  returned false, handle exception
    FETCH_ADVANCE_INST(3)                  #  advance rPC, load rINST
    GET_INST_OPCODE(t0)                    #  extract opcode from rINST
    GOTO_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<- method
    move      a1, rSELF                    #  a1<- self
    JAL(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解析,成功了!

<think>根据错误信息,任务`:app:processDebugResources`执行失败,原因是AAPT2在链接资源时发生意外错误。这通常与资源文件(如XML布局、图片等)中的错误有关,或者可能是AAPT2本身的bug。以下是一些解决步骤:###解决步骤:1.**检查资源文件**:-检查所有最近修改的布局文件(XML)、图片资源(如PNG、JPEG)等,确保它们没有错误。-特别注意错误日志中提到的具体资源文件,如果有,优先检查。2.**清理和重建**:-执行`Build>CleanProject`,然后`Build>RebuildProject`。3.**禁用AAPT2**(临时):-在`gradle.properties`文件中添加:```propertiesandroid.enableAapt2=false```-注意:AAPT2是默认的资源处理工具,禁用后使用旧版AAPT,但这是长期解决方案。4.**更新AndroidGradle插件**:-在项目根目录的`build.gradle`中,检查`dependencies`中的`classpath`,确保使用的是较新版本的AGP(AndroidGradlePlugin)。-例如:```groovydependencies{classpath'com.android.tools.build:gradle:7.0.4'}```-可以尝试更新到最新稳定版(如7.1.0或更高)。5.**检查资源文件中的非法字符**:-有时资源文件中的非法字符(如特殊Unicode字符)会导致AAPT2崩溃。检查字符串资源文件(`strings.xml`)等。6.**增加内存**:-在`gradle.properties`中增加AAPT2的内存限制:```propertiesorg.gradle.jvmargs=-Xmx4096m-XX:MaxPermSize=1024m```7.**检查图片资源**:-使用工具(如`pngcrush`)检查PNG图片是否有效,或者尝试移除最近添加的图片看是否解决问题。8.**查看详细错误日志**:-运行Gradle时加上`--stacktrace`、`--info`或`--debug`参数,例如:```./gradlewassembleDebug--stacktrace```-或者在AndroidStudio中,选择View>ToolWindows>Build,然后查看输出日志。###如果上述步骤无效,尝试以下:-**删除构建缓存**:在项目根目录运行:```./gradlewcleanBuildCache```或者手动删除`~/.gradle/caches/`目录(注意:这将清除所有项目的Gradle缓存)。-**更新AndroidSDKBuild-Tools**:确保安装的Build-Tools版本与`build.gradle`中配置的一致或更新。在`build.gradle`中:```groovyandroid{buildToolsVersion"30.0.3"}```-**禁用PNG压缩**(如果问题与PNG相关):在`build.gradle`中:```groovyandroid{aaptOptions{cruncherEnabled=false}}```###示例代码:在`gradle.properties`中设置禁用AAPT2```properties#临时禁用AAPT2android.enableAapt2=false```###解释:-步骤1和5是解决资源文件错误的根本方法。-步骤3是临时解决方案,因为AAPT2更严格,有时旧版AAPT可以绕过。-步骤4和8是更新和获取更多错误信息的方法。###相关问题:如果问题仍然存在,请提供更详细的错误日志(特别是AAPT2的错误输出)。§§相关问题§§:1.如何解读AAPT2错误日志中的具体错误信息?2.Android资源编译过程中常见的错误类型有哪些?3.如何为Android项目配置Gradle以使用更多内存?4.在Android开发中,如何批量检查资源文件的合法性?</think>## 解决 `:app:processDebugResources` 任务失败问题 这个错误表明 AAPT2(Android 资源打包工具)在资源处理过程中崩溃了。以下是系统性的解决方案: ### 解决方案 1:清理缓存和临时文件 ```bash # Windows gradlew clean gradlew stop del /f /q %USERPROFILE%\.android\cache\*.* del /f /q %USERPROFILE%\.gradle\caches\*.* # macOS/Linux ./gradlew clean ./gradlew stop rm -rf ~/.android/cache/* rm -rf ~/.gradle/caches/* ``` ### 解决方案 2:更新 Android Gradle 插件版本 在项目根目录的 `build.gradle` 中更新插件版本: ```groovy buildscript { repositories { google() mavenCentral() } dependencies { // 更新到最新稳定版(当前为 7.4.2) classpath 'com.android.tools.build:gradle:7.4.2' } } ``` ### 解决方案 3:配置 AAPT 选项 在 app 模块的 `build.gradle` 中增加以下配置: ```groovy android { // 增加 AAPT 选项 aaptOptions { cruncherEnabled = false additionalParameters '--no-version-vectors' ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~' } } ``` ### 解决方案 4:增加 JVM 堆内存 在 `gradle.properties` 文件中添加: ```properties # 增加 Gradle 内存 org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=1024m # 启用并行构建 org.gradle.parallel=true # 启用构建缓存 org.gradle.caching=true ``` ### 解决方案 5:检查资源文件问题 1. **检查所有 XML 资源文件**: - 确保没有未闭合的标签 - 检查属性值是否正确引号 - 验证所有资源引用(如 `@string/...`)是否存在 2. **检查图片资源**: - 验证所有图片格式是否正确(特别是 PNG 文件) - 尝试移除最近添加的图片资源测试 ### 解决方案 6:强制使用特定 AAPT2 版本 在 `gradle.properties` 中添加: ```properties # 强制使用特定 AAPT2 版本 android.aapt2FromMavenOverride=com.android.tools.build:aapt2:7.0.4-7396180 ``` ### 完整修复后的 `build.gradle` 示例 ```groovy apply plugin: 'com.android.application' android { compileSdkVersion 34 buildToolsVersion '30.0.3' defaultConfig { applicationId "com.hik.netsdk.SimpleDemo" minSdkVersion 21 targetSdkVersion 34 versionCode 11 versionName "3.0" vectorDrawables.useSupportLibrary = true multiDexEnabled true ndk { abiFilters "armeabi-v7a","arm64-v8a" } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } // 关键修复配置 aaptOptions { cruncherEnabled = false additionalParameters '--no-version-vectors' ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~' } packagingOptions { exclude 'META-INF/DEPENDENCIES' exclude 'META-INF/LICENSE' exclude 'META-INF/LICENSE.txt' exclude 'META-INF/license.txt' exclude 'META-INF/NOTICE' exclude 'META-INF/NOTICE.txt' exclude 'META-INF/notice.txt' exclude 'META-INF/ASL2.0' } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } dependencies { // 依赖项保持变 implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'com.google.android.material:material:1.5.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.3' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation ('io.github.ezviz-open:ezviz-sdk:5.20') { exclude group: 'com.ezviz.sdk', module: 'ezviz-sdk' } implementation ('com.ezviz.sdk:ezuikit:2.2.1') { exclude group: 'com.ezviz.sdk', module: 'ezviz-sdk' } implementation 'com.google.code.gson:gson:2.8.5' implementation 'com.squareup.okhttp3:okhttp:4.9.1' implementation "androidx.media3:media3-exoplayer:1.3.1" implementation "androidx.media3:media3-exoplayer-hls:1.3.1" implementation "androidx.media3:media3-ui:1.3.1" implementation "androidx.media3:media3-datasource-okhttp:1.3.1" coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4' implementation "androidx.media3:media3-common:1.3.1" } ``` ### 解决流程说明 1. **清理缓存**:AAPT2 错误常由损坏的缓存引起 2. **更新工具**:确保使用最新的构建工具版本 3. **配置优化**: - 禁用 PNG 处理 (`cruncherEnabled = false`) - 添加资源过滤规则 - 增加 JVM 内存分配 4. **依赖管理**:确保 EZVIZ SDK 依赖冲突已解决 5. **资源检查**:验证所有 XML 和图片资源有效性 ### 验证步骤 1. 执行清理命令 2. 同步 Gradle 项目 3. 重新构建项目 4. 检查 `:app:processDebugResources` 任务是否成功完成
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值