【问题标题】:How to debug a lambda expression using jdb如何使用 jdb 调试 lambda 表达式
【发布时间】:2016-08-23 22:42:17
【问题描述】:

我在集群生产服务器中遇到问题,我设法将单个实例与用户隔离,因此我可以将其用于调试,我正在使用 jdb 执行此操作。长介绍结束。我的问题是我需要将代码调试成 lambda 表达式

public void method(){
    this.privateField = Util.methodCall(); // Here the breakpoint works
    Clazz.staticMethod(() -> {
       Integer x = 1;
       Long y = 2; 
       y = x * y; // I need a Break point here
       /* 
         And a lot of non related code
       */
       });
}

当我在该行的 jdb 中创建断点时,它只是忽略了我的断点。我很确定调用该方法是因为断点到达方法的第一行,但只是忽略了另一个,我正在使用nextstep 命令,但不起作用。那么我的过程可能有什么问题?如何使用 jdb 调试 lambda 表达式?

【问题讨论】:

  • 你知道行号吗?您可以尝试“stop at MyClass:22”,其中 22 是行号,而 MyClass 是包含方法及其 lambda 表达式的内容。
  • 是的,我就是这样尝试的,但仍然无视我,我现在在想,这可能是 staticMethod 或上面的 lambda 的问题
  • Clazz.staticMethod(..) 期望的类型是什么?
  • 不记得了,应该是Callable

标签: java debugging lambda jdb


【解决方案1】:

这里是登陆并感兴趣的人的答案。

创建类

import java.util.concurrent.Callable;
public class Clazz {

    public static void main(String[] args) throws Exception {
        new Clazz().method();
    }

    public void method() throws Exception {
        Clazz.staticMethod(() -> {
            Integer x = 1;
            Long y = 2L;
            y = x * y; // I need a Break point here
            return y;
        });
    }

    private static void staticMethod(Callable i) throws Exception {
        System.out.println("i = " + i.call());
    }
}

编译

javac Clazz.java

为这个类启动 jdb

jdb Clazz
Initializing jdb ...

使用stop在main方法中设置断点

> stop in Clazz.main
Deferring breakpoint Clazz.main.
It will be set after the class is loaded.

使用run启动调试会话

> run
run Clazz
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
> 
VM Started: Set deferred breakpoint Clazz.main

Breakpoint hit: "thread=main", Clazz.main(), line=6 bci=0
6            new Clazz().method();

现在调试器在 main 方法中停止,就在调用 new Clazz().method(); 之前。

要找到我们感兴趣的行我们list

main[1] list
2    
3    public class Clazz {
4    
5        public static void main(String[] args) throws Exception {
6 =>         new Clazz().method();
7        }
8        
9        public void method() throws Exception {
10            Clazz.staticMethod(() -> {
11                Integer x = 1;
main[1] list 12
8        
9        public void method() throws Exception {
10            Clazz.staticMethod(() -> {
11                Integer x = 1;
12 =>             Long y = 2L;
13                y = x * y; // I need a Break point here
14                return y;
15            });
16        }
17    

需要命令list 12 来列出以下行。在输出中我们可以看到我们想要在13 行停止。所以让我们用stop 命令在那里设置一个新断点

main[1] stop at Clazz:13
Set breakpoint Clazz:13

要继续执行直到下一个断点发出命令cont

main[1] cont
> 
Breakpoint hit: "thread=main", Clazz.lambda$method$0(), line=13 bci=12
13                y = x * y; // I need a Break point here

我们不在线13,例如可以dumpxy 的值。

main[1] dump x
 x = {
    MIN_VALUE: -2147483648
    MAX_VALUE: 2147483647
    TYPE: instance of java.lang.Class(reflected class=int, id=568)
    digits: instance of char[36] (id=569)
    DigitTens: instance of char[100] (id=570)
    DigitOnes: instance of char[100] (id=571)
    sizeTable: instance of int[10] (id=572)
    value: 1
    SIZE: 32
    BYTES: 4
    serialVersionUID: 1360826667806852920
    java.lang.Number.serialVersionUID: -8742448824652078965
}
main[1] dump y
 y = {
    MIN_VALUE: -9223372036854775808
    MAX_VALUE: 9223372036854775807
    TYPE: instance of java.lang.Class(reflected class=long, id=574)
    value: 2
    SIZE: 64
    BYTES: 8
    serialVersionUID: 4290774380558885855
    java.lang.Number.serialVersionUID: -8742448824652078965
}

继续step 进一步

main[1] step
> 
Step completed: "thread=main", Clazz.lambda$method$0(), line=14 bci=26
14    

我们现在可以再次dump y 的值

main[1] dump y
 y = {
    MIN_VALUE: -9223372036854775808
    MAX_VALUE: 9223372036854775807
    TYPE: instance of java.lang.Class(reflected class=long, id=574)
    value: 2
    SIZE: 64
    BYTES: 8
    serialVersionUID: 4290774380558885855
    java.lang.Number.serialVersionUID: -8742448824652078965
}

【讨论】:

  • 谢谢你,遗憾的是我没有更多的问题实例,但答案正是我需要的。但是关于它的快速问题,您的编译器默认添加 -g 参数对吗?否则转储将无法引用xy
  • @carpinchosaurio 你是对的。如果在没有调试信息的情况下编译源代码,则无法转储变量。即使您可以使用stepi 逐步执行指令,您也无法转储变量或操作堆栈。
  • 正是我想要的。感谢你的回答。我需要使用 jdb 调试 Kotlin 代码,并且不能在 lambda 表达式中设置断点。将尝试您的方式并报告结果
  • 更新:jdb报告“xxx.kt source file not found”,将尝试指定kt source location
【解决方案2】:

看起来 jdb 上一次得到爱是在Java 6...

替代方案:IntelliJ 支持此功能(lambda 表达式中的断点)

【讨论】:

    猜你喜欢
    • 2014-08-23
    • 2013-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多