0

0

调试无响应的应用程序

王林

王林

发布时间:2024-08-13 08:30:40

|

594人浏览过

|

来源于dev.to

转载

阅读其他语言: english português 中文

有许多调试器教程可以教您如何设置行断点、记录值或计算表达式。虽然这些知识本身就为您提供了许多工具来调试应用程序,但实际场景可能会更复杂一些,并且需要更高级的方法。

在本文中,我们将学习如何在对项目没有太多了解的情况下找到导致 UI 崩溃的代码,并即时修复损坏的代码。

问题

如果您想遵循该示例,请首先克隆此存储库:https://github.com/flounder4130/debugger-example

假设您有一个复杂的应用程序,当您执行某些操作时该应用程序崩溃了。您知道如何重现错误,但困难在于您不知道代码的哪一部分负责此功能。

调试无响应的应用程序

在我们的示例应用程序中,当您单击按钮 N 时会发生崩溃。然而,要找到负责此操作的代码并不那么容易:

调试无响应的应用程序

让我们看看如何使用调试器来找到它。

方法断点

方法断点相对于行断点的优点是它们可以在整个类层次结构中使用。这对我们的例子有什么用?

如果您查看示例项目,您会发现所有操作类都派生自 Action 接口,并具有单个方法:perform()。

调试无响应的应用程序

在此接口方法上设置方法断点将在每次调用派生方法之一时暂停应用程序。要设置方法断点,请单击声明该方法的行。

启动调试会话并单击按钮N。应用程序在 ActionImpl14 上暂停。现在我们知道这个按钮对应的代码在哪里了。

调试无响应的应用程序

虽然在本文中我们的重点是查找错误,但当您想要了解某些内容在大型代码库中如何工作时,此技术也可以为您节省大量时间。

暂停应用程序

使用方法断点的方法效果很好,但它是基于我们了解父接口的假设。如果这个假设是错误的,或者我们由于其他原因不能使用这种方法怎么办?

好吧,我们甚至可以在没有断点的情况下做到这一点。单击按钮 N,当应用程序挂起时,转到 IntelliJ IDEA。从主菜单中,选择运行 | 调试操作 | 暂停计划.

调试无响应的应用程序

应用程序将暂停,允许我们在线程和变量选项卡中检查线程的当前状态。这让我们了解应用程序当时正在做什么。由于它挂起,我们可以识别导致阻塞的方法并将其追溯到调用站点。

这种方法比更传统的线程转储有一些优势,我们很快就会介绍。例如,它以方便的形式为您提供有关变量的信息,并允许您控制程序的进一步执行。

提示:有关暂停程序的更多提示和技巧,请参阅无断点调试和 Debugger.godMode()

线程转储

最后,我们可以使用线程转储,这并不是严格意义上的调试器功能。无论您是否使用调试器,它都可用。

Anakin
Anakin

一站式 AI 应用聚合平台,无代码的AI应用程序构建器

下载

单击按钮N。当应用程序崩溃时,转到 IntelliJ IDEA。从主菜单中,选择运行 | 调试操作 | 获取线程转储.

探索左侧的可用线程,在AWT-EventQueue中,您将看到导致问题的原因。

调试无响应的应用程序

线程转储的缺点是它们仅提供程序在创建时的状态快照。您不能使用线程转储来探索变量或控制程序执行。

在我们的示例中,我们不需要诉诸线程转储。但是,我仍然想提一下这种技术,因为它在其他情况下也很有用,例如当您尝试调试在没有调试代理的情况下启动的应用程序时。

了解问题所在

不管调试技术如何,我们都会到达 ActionImpl14。在此类中,有人打算在单独的线程中完成工作,但将 Thread.start() 与 Thread.run() 混淆了,后者在与调用代码相同的线程中运行代码。

IntelliJ IDEA 的静态分析器甚至在设计时警告我们:

调试无响应的应用程序

在 UI 线程上调用执行繁重任务(或在本例中休眠很多时间)的方法并阻塞该方法,直到该方法完成。这就是为什么我们在点击按钮 N后一段时间内无法在 UI 中执行任何操作。

热插拔

现在我们已经找到了错误的原因,让我们纠正问题吧。

我们可以停止程序,重新编译代码,然后再次运行。然而,仅仅因为做了一个小更改就重新部署整个应用程序并不总是明智的。

让我们用聪明的方式来做吧。首先,使用建议的快速修复修复代码:

调试无响应的应用程序

代码准备好后,点击运行 | 调试操作 | 重新加载更改的类。出现一个气球,确认新代码已到达虚拟机。

调试无响应的应用程序

让我们返回应用程序并检查一下。单击按钮 N 不再使应用程序崩溃。

提示:请记住,HotSwap 有其局限性。如果您对扩展的 HotSwap 功能感兴趣,那么看看 DCEVM 或 JRebel 等高级工具可能是个好主意

概括

使用我们的推理和一些调试器功能,我们能够找到导致项目中 UI 崩溃的代码。然后,我们继续修复代码,而不会浪费时间重新编译和重新分发,这在实际项目中可能会很长。

我希望您发现所描述的技术很有用。让我知道你的想法!

如果您对更多与调试和分析相关的文章感兴趣,请查看我的其他一些文章:

  • Debugger.godMode() – 使用调试器破解 JVM 应用程序
  • 解决调试器速度慢的问题
  • createDirectories() 有什么问题吗? - CPU 分析指南
  • 无断点调试

更多精彩敬请期待!

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

989

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

49

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

193

2025.12.29

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

467

2023.08.10

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

53

2025.12.01

idea快捷键大全
idea快捷键大全

本专题为大家提供idea快捷键相关的文章,帮助大家解决问题。

162

2023.08.03

idea如何集成Tomcat
idea如何集成Tomcat

idea集成Tomcat的步骤:1、添加Tomcat服务器配置;2、配置项目部署;3、运行Tomcat服务器;4、访问项目;5、注意事项;6、关闭Tomcat服务器。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

164

2024.02.23

idea怎么配置maven
idea怎么配置maven

idea配置maven的步骤:1、打开intellij idea,并确保已安装maven integration插件,可以在"file"菜单中选择"settings",然后在"plugins"选项卡中搜索并安装maven integration插件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

116

2024.02.23

桌面文件位置介绍
桌面文件位置介绍

本专题整合了桌面文件相关教程,阅读专题下面的文章了解更多内容。

0

2025.12.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Git 教程
Git 教程

共21课时 | 2.3万人学习

Git版本控制工具
Git版本控制工具

共8课时 | 1.5万人学习

Git中文开发手册
Git中文开发手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号