使用调试器进行事后跟踪
我最近一直在使用的大多数调试器的好功能是能够在断点上记录信息。 这对理解代码而无需修改是非常有用的,它涉及字节码修改。
让我们考虑一下这种非常琐碎且效率低下的函数实现,以返回斐波那契数列中的第n个数字。
public class Fib {public long fib(long number) {return number < 1 ? 0 : // Breakpoint herenumber < 2 ? 1 : fib(number - 2) + fib(number - 1);}public static void main(String[] args) {Fib fib = new Fib();System.out.println(fib.fib(10L));}}
现在我们添加一个简单的断点,我将对其进行一些修改,以使其不会停止; 但是它将记录一个简单的表达式,该表达式为我们提供了number
的当前值
这为我们效率不高的代码提供了以下输出:
ebugger connected to local process.
Source breakpoint: Fib.java:11, evaluate(number)=10 (long)
Source breakpoint: Fib.java:11, evaluate(number)=8 (long)
Source breakpoint: Fib.java:11, evaluate(number)=6 (long)
Source breakpoint: Fib.java:11, evaluate(number)=4 (long)
Source breakpoint: Fib.java:11, evaluate(number)=2 (long)
Source breakpoint: Fib.java:11, evaluate(number)=0 (long)
Source breakpoint: Fib.java:11, evaluate(number)=1 (long)
Source breakpoint: Fib.java:11, evaluate(number)=3 (long)
Source breakpoint: Fib.java:11, evaluate(number)=1 (long)
Source breakpoint: Fib.java:11, evaluate(number)=2 (long)
... sometime later
Source breakpoint: Fib.java:11, evaluate(number)=1 (long)
Source breakpoint: Fib.java:11, evaluate(number)=2 (long)
Source breakpoint: Fib.java:11, evaluate(number)=0 (long)
Source breakpoint: Fib.java:11, evaluate(number)=1 (long)
55
因此,我们在此处所做的就是添加事后跟踪,您甚至可能无法访问源,仍然能够从代码的工作中获取有用的信息。
现在,与上面的示例明显不同的是,我们一次又一次地计算相同的值。 因此,这里是代码的另一个版本,它使用Map来存储序列中先前计算的值。 还请注意,在不使Lambda变得不那么漂亮的情况下,将跟踪添加到此代码比在以前的情况下更加痛苦。
import java.util.HashMap;
import java.util.Map;public class Fib {Map<Long, Long> data = new HashMap<>();{data.put(1L, 1L);}public long fib(long number) {return data.computeIfAbsent(number,n -> n < 1 ? 0 : fib(n - 2) + fib(n - 1)); // Breakpoint here}public static void main(String[] args) {Fib fib = new Fib();System.out.println(fib.fib(10L));}}
这里需要注意两件事,首先,断点日志表达式应评估Lambda参数n
的值,其次是您应始终将表达式放在新行上,以便将来的开发人员可以轻松地对其进行断点。 (现在,如果将代码放在一个代码上,看起来会显得小得多/漂亮/聪明)。
因此,跟踪输出现在如下所示,因为每个值只计算一次,所以效果更好。
Debugger connected to local process.
Source breakpoint: Fib.java:17, evaluate(n)=10
Source breakpoint: Fib.java:17, evaluate(n)=8
Source breakpoint: Fib.java:17, evaluate(n)=6
Source breakpoint: Fib.java:17, evaluate(n)=4
Source breakpoint: Fib.java:17, evaluate(n)=2
Source breakpoint: Fib.java:17, evaluate(n)=0
Source breakpoint: Fib.java:17, evaluate(n)=3
Source breakpoint: Fib.java:17, evaluate(n)=5
Source breakpoint: Fib.java:17, evaluate(n)=7
Source breakpoint: Fib.java:17, evaluate(n)=9
55
该博客中的屏幕截图来自Jdeveloper。 但是Intelij和Netbeans中提供了类似的功能,如果您比较精明 ,可以在Eclipse中获得类似的功能。
翻译自: https://www.javacodegeeks.com/2014/01/post-hoc-tracing-using-a-debugger.html
使用调试器进行事后跟踪相关推荐
- 如何利用ide进行跟踪调试_使用调试器进行事后跟踪
如何利用ide进行跟踪调试 我最近一直在使用的大多数调试器的好功能是能够在断点上记录信息. 这对于理解代码而无需修改是非常有用的,因为它涉及字节码修改. 让我们考虑一下这种非常琐碎且效率低下的函数实现 ...
- 转载 调试器工作原理
调试器工作原理--基础篇 本文是一系列探究调试器工作原理的文章的第一篇.我还不确定这个系列需要包括多少篇文章以及它们所涵盖的主题,但我打算从基础知识开始说起. 关于本文 我打算在这篇文章中介绍关于Li ...
- Linux下调试器工作原理
Linux下调试器工作原理之一-基础篇 介绍关于Linux下的调试器实现的主要组成部分--ptrace系统调用.本文中出现的代码都在32位的Ubuntu系统上开发.请注意,这里出现的代码是同平台紧密相 ...
- 调试器工作原理系列三篇
基础篇 关于本文 我打算在这篇文章中介绍关于Linux下的调试器实现的主要组成部分--ptrace系统调用.本文中出现的代码都在32位的Ubuntu系统上开发.请注意,这里出现的代码是同平台紧密相关的 ...
- [Win32]一个调试器的实现(五)调试符号
一个调试器应该可以跟踪被调试程序执行到了什么地方,显示下一条将要执行的语句,显示各个变量的值,设置断点,进行单步执行等等,这些功能都需要一个基础设施的支持,那就是调试符号. 什么是调试符号 我们知道, ...
- IntelliJ IDEA 2017.1 EAP与异步堆栈跟踪调试器扩展
反应性编程趋势后,我们的代码越来越异步. 早些时候java8介绍了CompletableFuture(采用Guava's ListenableFuture),通过Akka, Ratpack, Reac ...
- 手机怎么安装py thon_Python调试器– Python pdb
手机怎么安装py thon Python pdb module provides an interactive debugging environment for Developers to debu ...
- pdb—Python调试器
pdb-Python调试器 在python 3.8文档 Python 常用指引中已经详细介绍了pdb模块,此处为引用官方文档 该模块pdb为Python程序定义了一个交互式源代码调试器.它支持在源代码 ...
- Python调试器-Pdb的简介及调试命令
Pdb简介 pdb为Python程序定义了一个交互式源代码调试器.它支持在源代码行级别设置(条件)断点和单步执行,检查堆栈框架,源代码列表以及在任何堆栈框架的上下文中评估任意Python代码.它还支持 ...
最新文章
- 为何 Windows 10X 无法延续 Windows 的成功?
- COMMUNITY SERVER 的架构分析
- 程序员面试【Brainteasers】
- (八) stm8程序段定位,理解lkf文件
- prfm预加载指令使用说明
- ChaiNext:大盘调整,主流币种还未稳住阻力位
- SQL Server 2019中的行模式内存授予反馈
- 新疆哈巴河冰雪旅游节开幕 游人沉醉雪舞冰封“第一桦”
- Lc123验证是不是回文序列
- bodymovin导出没有html5,Bodymovin导出Json文件避坑指南
- 机器学习中数据标准化相关方法
- 阿里云-钉钉-企业邮箱
- VB中的ByVal和ByRef的区别
- 命令之 dirname
- 如何解决java中的安全问题_如何解决java中“使用了未经检查或不安全的操作 请使用 -Xlint:unchecked 重新编译 ”的问题...
- 利用conda创建、激活和删除新环境。
- 微信小程序中使用slot插槽
- mac 特殊符号的操作
- 四点共面(混合积 x 乘 与 . ”乘)
- 抖音为何要自研芯片?
热门文章
- java jpa saveall方法优化_JPA批量插入(saveAll)
- (转)Spring Boot通过ImportBeanDefinitionRegistrar动态注入Bean
- (转)【SpringMvc】如何使用form发送PUT和DELETE请求
- 设计模式入门(策略模式)
- Java 泛型实现方法 — 擦拭法
- vue 侦听器侦听对象属性_Spring中的异步和事务性事件侦听器
- jax-ws和jax-rs_带有JAX-WS和Spring的Web服务应用程序
- bean创建异常_快速提示:消息驱动Bean中的异常处理
- java 性能调优_Java性能调优调查结果(第二部分)
- 如何在Java JVM中处理图像和视频