我最近一直在使用的大多数调试器的好功能是能够在断点上记录信息。 这对理解代码而无需修改是非常有用的,它涉及字节码修改。
让我们考虑一下这种非常琐碎且效率低下的函数实现,以返回斐波那契数列中的第n个数字。
public class Fib {
public long fib(long number) {
return number < 1 ? 0 : // Breakpoint here
number < 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