java trace process_Android打印Trace堆栈

2023-05-16

本文介绍一些Android常见的调试技巧

一. 获取Trace

调用栈信息(Trace)是分析异常经常使用的,这里简单划分两类情况:

当前线程Trace: 当前执行流所在线程的调用栈信息;

目标进程Trace:可获取目标进程的调用栈,用于动态调试;

1.1 当前线程Trace

1) Java层

Thread.currentThread().dumpStack(); //方法1

Log.d(TAG,"Gityuan", new RuntimeException("Gityuan")); //方法2

new RuntimeException("Gityuan").printStackTrace(); //方法3

2) Native层

#include

android::CallStack stack(("Gityuan"));

1.2 目标进程Trace

1) Java层

adb shell kill -3 [pid] //方法1

Process.sendSignal(pid, Process.SIGNAL_QUIT) //方法2

生成trace文件保存在文件data/anr/traces.txt

2) Native层

adb shell debuggerd -b [tid] //方法1

Debug.dumpNativeBacktraceToFile(pid, tracesPath) //方法2

前两条命令输出内容相同:

命令1输出到控制台

命令2输出到目标文件

对于debuggerd命令,若不带参数则输出tombstones文件,保存到目录/data/tombstones

3) Kernel层

adb shell cat /proc/[tid]/stack //方法1

WatchDog.dumpKernelStackTraces() //方法2

其中dumpKernelStackTraces()只能用于打印当前进程的kernel线程

1.3 小节

以下分别列举输出Java, Native, Kernel的调用栈方式:

类别

函数式

命令式

Java

Process.sendSignal(pid, Process.SIGNAL_QUIT)

kill -3 [pid]

Native

Debug.dumpNativeBacktraceToFile(pid, tracesPath)

debuggerd -b [pid]

Kernel

WD.dumpKernelStackTraces()

cat /proc/[tid]/stack

分析异常时往往需要关注的重要目录:

/data/anr/traces.txt

/data/tombstones/tombstone_X

/data/system/dropbox/

二. 时间调试

为了定位耗时过程,有时需要在关注点添加相应的systrace,而systrace可跟踪系统cpu,io以及各个子系统运行状态等信息,对于kernel是利用Linux的ftrace功能。当然也可以直接在方法前后加时间戳,输出log的方式来分析。

2.1 新增systrace

1) App

import android.os.Trace;

void foo() {

Trace.beginSection("app:foo");

...

Trace.endSection();

}

2) Java Framework

import android.os.Trace;

void foo() {

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "fw:foo");

...

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

}

3) Native Framework

#define ATRACE_TAG ATRACE_TAG_GITYUAN

#include // used for C++

#include // used for C

void foo() {

ATRACE_CALL();

...

}

或者

#define ATRACE_TAG ATRACE_TAG_GITYUAN

#include // used for C++

#include // used for C

void foo() {

ATRACE_BEGIN();

...

ATRACE_END();

}

2.2 打印时间戳

1) Java

import android.util.Log;

void foo(){

long startTime = System.currentTimeMillis();

...

long spendTime = System.currentTimeMillis() - startTime;

Log.i(TAG,"took " + spendTime + “ ms.”);

}

2) C/C++

#include

#include

void foo() {

struct timeval time;

gettimeofday(&time, NULL); //精度us

printf("took %lld ms.\n", time.tv_sec * 1000 + time.tv_usec /1000);

}

2.3 kernel log

有时候Kernel log的输出是由级别限制,可通过如下命令查看:

adb shell cat /proc/sys/kernel/printk

4 4 1 7

参数解读:

控制台日志级别:优先级高于该值的消息将被打印至控制台。

缺省的消息日志级别:将用该值来打印没有优先级的消息。

最低的控制台日志级别:控制台日志级别可能被设置的最小值。

缺省的控制台日志级别:控制台日志级别的缺省值

日志级别:

级别

说明

KERN_EMERG

0

致命错误

KERN_ALERT

1

报告消息

KERN_CRIT

2

严重异常

KERN_ERR

3

出错

KERN_WARNING

4

警告

KERN_NOTICE

5

通知

KERN_INFO

6

常规

KERN_DEBUG

7

调试

Log相关命令

dmesg 或 cat /proc/kmsg

logcat -L 或 cat /proc/last_kmsg

logcat -b events -b system

三. addr2line

addr2line功能是将函数地址解析为函数名。分析过Native Crash,那么对addr2line一定不会陌生。 addr2line命令参数:

Usage: addr2line [option(s)] [addr(s)]

The options are:

@ Read options from

-a --addresses Show addresses

-b --target= Set the binary file format

-e --exe= Set the input file name (default is a.out)

-i --inlines Unwind inlined functions

-j --section= Read section-relative offsets instead of addresses

-p --pretty-print Make the output easier to read for humans

-s --basenames Strip directory names

-f --functions Show function names

-C --demangle[=style] Demangle function names

-h --help Display this information

-v --version Display the program's version

3.1 Native地址转换

Step 1: 获取symbols表

先获取对应版本的symbols,即可找到对应的so库。(最好是对应版本addr2line,可确保完全匹配)

Step 2: 执行addr2line命令

// 64位

cd prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin

./aarch64-linux-android-addr2line -f -C -e libxxx.so

//32位

cd /prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin

./arm-linux-androideabi-addr2line -f -C -e libxxx.so

另外,有兴趣可以研究下development/scripts/stack,地址批量转换工具。

3.2 kernel地址转换

addr2line也适用于调试分析Linux Kernel的问题。例如,查询如下命令所对应的代码行号

[<0000000000000000>] binder_thread_read+0x2a0/0x324

Step 1: 获取符号地址

通过命令arm-eabi-nm从vmlinux找到目标方法的符号地址,其中nm和vmlinux所在目录:

arm-eabi-nm位于目录prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/

vmlinux位于目录out/target/product/xxx/obj/KERNEL_OBJ/

执行如下命令:(需要带上绝对目录)

arm-eabi-nm vmlinux |grep binder_thread_read

则输出结果: c02b2f28 T binder_thread_read,可知binder_thread_read的符号地址为c02b2f28, 其偏移量为0x2a0,则计算后的目标符号地址= c02b2f28 + 2a0,然后再采用addr2line转换得到方法所对应的行数

Step 2: 执行addr2line命令

./aarch64-linux-android-addr2line -f -C -e vmlinux [目标地址]

注意:对于kernel调用栈翻译过程都是通过vmlinux来获取的

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java trace process_Android打印Trace堆栈 的相关文章

  • 无法读取第 0 行,第 -1 列

    我正在尝试复制使用 SQLite 管理器创建的数据库 我在其中执行了以下操作 CREATE TABLE android metadata locale TEXT DEFAULT en US and INSERT INTO android m
  • 使用正则表达式验证电子邮件的最大长度

    我找到了用于电子邮件验证的正则表达式 a z0 9 a z0 9 a z0 9 a z0 9 a z 2 4 我希望电子邮件的最大长度为 20 个字符 因此我将其更改为 a z0 9 a z0 9 a z0 9 a z0 9 a z 2 4
  • 如何检查单词是否在wordNet中

    我开始了解wordNet直到我知道我找到了synonymous对于一个特定的词 现在我有一个文件 我想使用标记化该文本n gram例如 String s I like to wear tee shirt 使用后n gram这将是 I lik
  • 我的 Kafka 流应用程序刚刚退出,代码为 0,什么也不做

    为了尝试 Kafka 流 我这样做了 public static void main String args final StreamsBuilder builder new StreamsBuilder final Properties
  • java.exe 以非零退出值 1 结束

    只是为了开始 我并不是真正尝试从 Android 中的 xlsx 文件中读取单元格 我已经尝试了几乎所有我在 Google 上搜索到的内容 但是每次 在两台不同的 PC 上 都是 Java 1 7 0 79 当我尝试构建 运行 这个应用程序
  • java绕中心旋转矩形

    我想围绕其中心点旋转一个矩形 它应该保留在应该绘制的位置并在该空间中旋转 这是我的代码 AffineTransform transform new AffineTransform transform rotate Math toRadian
  • 始终将双精度舍入

    我怎么总是能把一个double to an int 并且永远不要将其四舍五入 我知道Math round double 但我希望它始终向上舍入 所以如果是的话3 2 四舍五入为 4 您可以使用Math ceil method 请参阅Java
  • 向Java类库添加函数

    我使用的 Java 类库在很多方面都不完整 有很多类我认为应该内置其他成员函数 但是 我不确定添加这些成员函数的最佳实践 让我们调用不足的基类A class A public A long arbitrary arguments publi
  • 什么是版本代码主要?和versionCode有什么区别?

    我刚刚发现PackageInfo versionCode https developer android com reference android content pm PackageInfo html versionCode在 Andr
  • log4j.properties 在 Wildfly 上无法正常工作

    我的类路径中有一个 log4j properties 文件 它位于 APP XX jar log4j properties 位置 我注意到在ear文件中我还可以在lib文件夹中找到log4j 1 2 17 jar 但无论我在 log4j p
  • 在 Tensorflow-lite Android 中将位图转换为 ByteBuffer(浮点)

    在用于图像分类的tensorflow lite android演示代码中 图像首先转换为ByteBuffer格式以获得更好的性能 这种从位图到浮点格式的转换以及随后到字节缓冲区的转换似乎是一个昂贵的操作 循环 按位运算符 float mem
  • 在 Spring MVC 中将请求写入文件

    我希望能够将整个请求写入 Spring MVC 控制器中的文件 我已尝试以下操作 但即使我使用大量参数发出 POST 请求 文件也始终为空 RequestMapping method RequestMethod POST value pay
  • 难以理解 通配符

    我有一个非常基本的问题 下面的代码无法编译 假设 Apple Extends Fruit List
  • 用于生成 ISO 文件的 Maven 插件

    有没有可以生成ISO镜像的maven插件 我需要获取一些模块的输出 主要是包含 jar 的 zip 文件 并将它们组合成一个 ISO 映像 Thanks 现在有一个 ISO9660 maven 插件可以完成这项工作 https github
  • 使用 Android O 的“android:fontFamily”时出现错误“文件名必须以 .xml 结尾”?

    Android O 引入了一项新功能 XML 中的字体 它允许您将字体用作资源 我正在创建font资源文件中的文件夹 由安卓开发者 https developer android com preview features working w
  • 亚马逊 Linux - 安装 openjdk-debuginfo?

    我试图使用jstack在 ec2 实例上amazon linux 所以我安装了openjdk devel包裹 sudo yum install java 1 7 0 openjdk devel x86 64 但是 jstack 引发了异常j
  • Android IntentService无法实例化类;没有空构造函数

    我有一个MainActivity需要访问在线 API 从而使用网络资源 的类 这需要我在单独的文件中创建的后台线程HttpRequestService java MainActivity java public class MainActi
  • Axis2 的 wsdl2java 在 RPC/Encoded 样式 Web 服务上失败

    Axis2 有替代方案吗 或者让它工作的方式 例如不同的数据绑定 Retrieving document at Exception in thread main org apache axis2 wsdl codegen CodeGener
  • Graphics2D setfont() 严重减慢了 java 应用程序的启动速度

    我正在用java制作一个游戏 它每秒刷新60次 每次执行循环时 我都会使用 g2d 来绘制图像和字符串 如果我这样做的话一切都会很好g2d setFont new Font Arial Font PLAIN 8 和抽绳 这将是正常的 但如果
  • Android 可扩展列表视图随机播放子项

    你好 我正在使用 Android Expandable listview 并用不同的视图在其中膨胀子视图 我遇到的问题是 当我展开视图然后打开另一个父视图时 布局中的子视图会变得混乱并在代码中膨胀错误的布局 这是我的两个项目的示例代码 这是

随机推荐