可调试的build变体的操作及其他任务的说明
发表时间:2023-09-02 19:03:07
文章来源:炫佑科技
浏览次数:186
菏泽炫佑科技
可调试的build变体的操作及其他任务的说明
提供调试器来执行以下操作和其他任务:
此页面包含基本调试器操作的说明。 有关更多文档,另请参阅 IDEA 调试文档。
启用调试
在开始调试之前,您需要执行以下操作:
在设备上启用调试。
如果您使用模拟器,则默认启用调试。 但是,对于连接的设备,您需要在设备开发人员选项中启用调试。
运行可调试的构建变体。
使用构建配置中包含的构建变体 (=true)。
通常,您可以选择每个项目中包含的默认“调试”变体(即使它在 build. 文件中不可见)。 但是,如果要将新的构建类型定义为可调试,则必须将 true 添加到构建类型:
android { buildTypes { customDebugType { debuggable true ... } } }
android { buildTypes { create("customDebugType") { isDebuggable = true ... } } }
此属性也适用于包含 C/C++ 代码的模块。
注意:该属性已被弃用。
如果您的应用程序依赖于您也想调试的库模块,则该库也必须使用 true 进行打包,以便保留其调试符号。 为了确保应用程序项目的可调试变体接收库模块的可调试变体,请发布库的非默认版本。
开始调试
您可以按如下方式启动调试会话:
在应用程序代码中设置一些。 在工具栏中,从目标设备菜单中选择用于调试应用程序的设备。
图 1. 目标设备菜单。
如果您尚未配置任何设备,则需要或使用模拟器。
在工具栏中,单击“调试”图标
。
如果您的应用程序已在设备上运行,则会出现一个对话框,询问您是否要从“运行”切换到“调试”。 您需要重新启动设备才能开始调试。 要保持同一应用程序实例运行,请单击“调试”。 否则,构建 APK,使用调试密钥对其进行签名,将其安装在您选择的设备上,然后运行它。
如果您将 C 和 C++ 代码添加到项目中,它还会在“调试”窗口中运行 LLDB 调试器来调试您的本机代码。
如果“调试”窗口未打开,请选择“视图”>“工具”>“调试”,或单击工具窗口栏中的“调试”图标
。 单击“”选项卡,如图1所示。
图 2. 显示变量的当前线程和对象树的“调试”窗口将调试器连接到正在运行的应用程序
如果您的应用程序已在设备上运行,则无需重新启动应用程序即可开始调试,如下所示:
单击“至”图标
。 在对话框中,选择要附加调试器的进程。 如果您使用的是模拟器或已取得 root 权限的设备,则可以选中“全部显示”以查看所有进程。 在已取得 root 权限的设备上,执行此操作将显示设备上运行的所有进程。 但是,在非 root 设备上,执行此操作只会显示可调试进程。 从“使用自”菜单中,您可以选择现有的运行/调试配置。 对于 C 和 C++ 代码,您可以重用现有配置中的 LLDB 启动命令、LLDB 连接后命令和符号目录。 如果您没有现有的运行/调试配置,请选择新建。 此选项可启用“调试类型”菜单。 默认情况下,自动调试类型用于选择*适合您的调试器选项,具体取决于您的项目包含 Java 代码还是 C/C++ 代码。 单击“确定”。
然后将显示“调试”窗口。
设备浏览器中的选项卡(查看 > 工具 > )还包含可调试进程的列表。您可以从中选择一个进程并执行终止
或强制停止
操作,或将调试器附加到给定进程
。
注意:调试器与垃圾收集器松散集成。 虚拟机保证调试器发现的任何对象在调试器断开连接之前都不会被垃圾收集。 这可能会导致调试器连接时对象堆积。 例如,如果调试器发现正在运行的线程,则即使该线程终止,关联的对象也不会在调试器断开连接之前被垃圾回收。
更改调试器类型
由于调试 Java/Code 和 C/C++ 代码需要不同的调试器工具,因此 允许您选择要使用的调试器类型。 默认情况下,使用哪个调试器(使用自动调试器类型)是根据项目中检测到的语言确定的。
要在调试配置中手动选择调试器,请单击运行 > 编辑。 您还可以在单击“运行”>“到”后显示的对话框中选择调试程序。
可用的调试类型包括:
汽车
如果您想要自动为您正在调试的代码选择*合适的选项,请选择此调试类型。 例如,如果您的项目包含任何 C 或 C++ 代码,则会自动使用“双”调试类型。 否则,将使用“Java”调试类型。
爪哇
如果您只想调试用 Java 或 . Java 调试器会忽略您在本机代码中设置的任何断点或观察点。
(仅适用于 C/C++ 代码)
如果您只想使用 LLDB 调试代码,请选择此调试类型。 使用此调试类型时,Java 调试器会话视图不可用。 默认情况下,LLDB 仅检查本机代码并忽略 Java 代码中的断点。 如果您还想调试 Java 代码,则应切换到“自动”或“双”调试类型。
本机调试仅在满足以下要求的设备上可用:
双(仅适用于 C/C++ 代码)
如果您想同时在调试 Java 代码和本机代码之间切换,请选择此调试类型。 Java 调试器和 LLDB 都连接到您的应用程序进程,因此您可以检查 Java 和本机代码中的断点,而无需重新启动应用程序或更改调试配置。
在图 2 中,请注意调试窗口标题右侧的两个选项卡。 由于应用程序同时包含 Java 和 C++ 代码,因此一个选项卡用于调试本机代码,另一个选项卡用于调试 Java 代码(如 -java 所示)。
图 3. 用于调试本机代码的选项卡和用于调试 Java 代码的选项卡。
注意:在调试编译器优化的本机代码时,您可能会收到以下警告消息:
这是与. 有些可能不是。 当您使用优化标志时,编译器会对编译后的代码进行更改以使其运行更高效。 这可能会导致调试器报告意外或不正确的信息,因为调试器很难将优化的编译代码映射回原始源代码。 因此,在调试本机代码时应禁用编译器优化。
使用系统日志
当您调试应用程序时,系统日志会显示系统消息。 这些消息包括设备上运行的应用程序生成的信息。 如果您使用系统日志来调试应用程序,请确保您的代码在应用程序开发过程中写入日志消息并输出异常的堆栈跟踪。
在代码中写入日志消息
要在代码中写入日志消息,请使用 Log 类。 日志消息通过在您与应用程序交互时收集系统调试输出来帮助您了解执行流程。 日志消息还可以告诉您应用程序的哪一部分出现故障。 有关日志记录的更多信息,请参阅使用写入和查看日志。
以下示例显示如何添加日志消息以确定启动时先前的状态信息是否可用:
import android.util.Log ... private val TAG: String = MyActivity::class.java.simpleName ... class MyActivity : Activity() { ... override fun onCreate(savedInstanceState: Bundle?) { ... if (savedInstanceState != null) { Log.d(TAG, "onCreate() Restoring previous state") /* restore state */ } else { Log.d(TAG, "onCreate() No saved state available") /* initialize app */ } } }
爪哇
import android.util.Log; ... public class MyActivity extends Activity { private static final String TAG = MyActivity.class.getSimpleName(); ... @Override public void onCreate(Bundle savedInstanceState) { ... if (savedInstanceState != null) { Log.d(TAG, "onCreate() Restoring previous state"); /* restore state */ } else { Log.d(TAG, "onCreate() No saved state available"); /* initialize app */ } } }
在开发过程中,您的代码还可以捕获异常并将堆栈跟踪写入系统日志:
fun someOtherMethod() { try { ... } catch (e : SomeException) { Log.d(TAG, "someOtherMethod()", e) } }
爪哇
void someOtherMethod() { try { ... } catch (SomeException e) { Log.d(TAG, "someOtherMethod()", e); } }
注意:当您准备好发布应用程序时,您应该从代码中删除调试日志消息和堆栈跟踪输出调用。 为此app开发,请设置 DEBUG 标志并将调试日志消息放入条件语句中。
查看系统日志
您可以在“”窗口中查看和过滤调试消息和其他系统消息,如图 4 所示。例如,您可以查看发生垃圾收集时出现的消息,或者使用 Log 类添加到应用程序中的消息。
要使用,请选择“”选项卡。
图 4.带有过滤器设置的“”窗口。
有关其过滤选项的说明,请参阅使用写入和查看日志。
使用断点
支持多个断点,可以触发不同的调试操作。 断点有以下几种类型:
行断点
*常见的类型是行断点,它在指定的代码行暂停应用程序的执行。 暂停时,您可以检查变量、计算表达式并继续逐行执行以确定运行时错误的原因。
方法断点
方法断点会在进入或退出特定方法时暂停应用程序的执行。 暂停时,您可以检查变量、计算表达式并继续逐行执行以确定运行时错误的原因。
字段断点
读取或写入特定字段时,字段断点会暂停应用程序的执行。
异常断点
当对特定字段执行读取或写入操作时,异常断点会暂停应用程序的执行。
您可以设置条件断点,仅在满足特定条件时暂停应用程序的执行。 您还可以设置日志记录断点,这些断点会写入执行而不暂停它。 这有助于避免日志语句中出现乱码代码。
要添加行断点,请按照下列步骤操作:
找到要暂停执行的代码行。 单击代码行的左边框,或将光标放在该行上并按 Ctrl+F8(macOS 上为 +F8)。如果您的应用程序已在运行,请单击“to”图标
.否则,要开始调试,请单击“调试”图标
。
设置断点时,相应代码行旁边会出现一个红点,如图 5 所示。
图 5. 设置断点时,相应代码行旁边会出现一个红点。
当您的代码执行到达此断点时,应用程序的执行将暂停。
要确定应用程序的状态,请使用“”选项卡上的工具:
如果您的项目使用任何本机代码,则“自动”调试类型默认将 Java 调试器和 LLDB 作为两个单独的进程连接到您的应用程序。 这样,您可以在检查 Java 断点和 C/C++ 断点之间切换,而无需重新启动应用程序或更改设置。
注意:要检测 C 或 C++ 代码中的断点,您需要使用支持 LLDB 的调试类型,例如 Auto 或 Dual。 您可以通过修改调试配置来更改使用的调试类型。 要了解有关不同调试类型的更多信息,请阅读“使用其他调试类型”部分。
当应用程序部署到目标设备时,“调试”窗口将打开,显示每个调试器进程的选项卡或调试会话视图,如图 6 所示。
图 6. 使用 LLDB 调试本机代码。 当 LLDB 调试器在 C/C++ 代码中遇到断点时,它会切换到选项卡。 还会显示“””和“”窗格,其功能与调试 Java 代码时完全相同。
尽管 LLDB 会话视图不显示该窗格,但您可以使用该窗格中的列表来访问您的应用程序进程。 您可以在有关如何和的部分中了解有关这些窗格的更多信息。
注意:检查本机代码中的断点时,系统会挂起运行应用程序 Java 字节码的虚拟机。 这意味着在检查本机代码中的断点时,您无法与 Java 调试器交互或从 Java 调试器会话检索任何状态信息。
当 Java 调试器在 Java 或代码中遇到断点时,它会切换到 -java 选项卡。 使用 LLDB 进行调试时,可以使用 LLDB 会话视图中的 LLDB 终端将命令行选项传递给 LLDB。 如果您希望 LLDB 在每次开始调试应用程序时(在调试器连接到应用程序进程之前或之后)执行某些命令,您可以。
调试 C/C++ 代码时,您还可以设置特殊类型的断点(称为观察点),这些断点会在应用程序进程与特定内存块交互时挂起应用程序进程。 要了解更多信息,请阅读有关如何操作的部分。
查看和配置断点
要查看所有断点并配置断点设置,请单击“调试”窗口中的“查看”图标
。 将出现“”窗口,如图 7 所示。
图 7.“”窗口列出了所有当前断点,并包括每个断点的行为设置。
您可以启用或禁用“”窗口中列表中的每个断点。 如果禁用断点,则应用程序在遇到断点时不会停止。
从列表中选择一个断点以配置其设置。 您可以将断点配置为*初禁用,并在遇到其他断点后启用它。 您还可以配置断点在命中后是否应被禁用。 要为任何异常设置断点,请在断点列表中选择它。
调试窗框
在“”窗口的“”窗格中,您可以检查导致遇到当前断点的堆栈帧。 这允许您浏览和检查堆栈帧,同时还检查应用程序中的线程列表。
要选择线程,请使用线程选择器菜单并查看其堆栈帧。 单击框架中的元素会在编辑器中打开源代码。 您还可以自定义线程渲染并导出堆栈帧,如中所述
检查变量
当您的应用程序在断点处停止并从窗格中选择一个框架后,您可以检查窗口窗格中的变量。 此外,您可以使用所选框架中可用的静态方法和/或变量来计算窗格中的临时表达式。
“”窗格提供类似的功能,不同之处在于添加到“”窗格的表达式在调试会话中持续存在。 为您经常访问的变量和字段添加观察点,或提供对当前调试会话有帮助的状态。 “”和“”窗格如图 8 所示。
要将变量或表达式添加到“”列表,请按照下列步骤操作:
开始调试。在窗格中,单击“添加”图标
。 在出现的文本框中,输入要监视的变量或表达式的名称,然后按 Enter。
要从“”列表中删除项目,请选择该项目并单击 图标
。
要对“”列表中的元素重新排序,请选择一个项目并单击向上图标
或向下图标
。
图 8. “调试”窗口中的“”和“”窗格。添加观察点
调试 C/C++ 代码时,您可以设置特殊类型的断点(称为观察点),这些断点会在应用程序与特定内存块交互时挂起应用程序的进程。 例如,如果为一个内存块设置两个指针并为其分配一个观察点,则使用任一指针访问该内存块都会触发该观察点。
在 中,您可以通过选择特定变量在运行时创建观察点,但 LLDB 只会将观察点分配给系统分配给该变量的内存块,而不是分配给变量本身。 这与将变量添加到“”窗格不同可调试的build变体的操作及其他任务的说明,后者允许您监视变量的值,但不允许您在系统读取或更改内存中的变量值时挂起应用程序进程。
注意:当应用程序进程退出函数并且系统从内存中释放其局部变量时,您需要重新分配为这些变量创建的所有观察点。
要设置观察点,您必须满足以下要求:
注意:使用 32 位 ARM ABI 调试应用程序时,添加观察点或将鼠标悬停在代码中的变量上以检查其值可能会导致崩溃。 要解决此问题,请使用 64 位 ARM、x86 或二进制文件进行调试。 此问题将在即将发布的版本中得到解决。
如果满足上述要求,则可以添加观察点。 具体步骤如下:
当应用程序挂在断点处时,转到 LLDB 会话视图窗格。
右键单击占用要跟踪的内存块的变量,然后选择“添加”。
图 9.向内存中的变量添加观察点。
将出现配置观察点的对话框,如图9所示。
使用以下选项配置您的观察点:
单击“完成”。
要查看所有观察点并配置观察点设置,请单击“调试”窗口中的“查看”图标
。 弹出“”对话框,如图10所示。
图 10.“”对话框列出了当前观察点并包括每个观察点的行为设置。
添加监控点后,点击“调试”窗口中的图标
应用程序进程可以继续执行。默认情况下,如果应用程序尝试访问您设置了观察点的内存块,系统会挂起该应用程序进程,并且该应用程序执行的*后一行代码旁边会出现一个观察点图标。应用程序。
,如图11所示。
图 11. 指示应用程序在触发观察点之前执行的代码行。查看和更改资源值显示格式
在调试模式下,您可以查看Java或代码中变量的资源值,并为其选择其他显示格式。 显示“”选项卡并选择框架后,执行以下操作:
在列表中,右键单击资源行中的任意位置可显示列表。 选择列表中的查看方式并选择您要使用的格式。
可供选择的格式取决于所选资源的数据类型。 您可能会看到以下一个或多个选项:
要创建自定义格式,请执行以下操作:
右键单击资源值。 选择查看方式。 选择。 将出现“Java 数据类型”对话框。 请遵循 Java 数据类型渲染器中的说明。