为变量分配某个值时中断
Posted
技术标签:
【中文标题】为变量分配某个值时中断【英文标题】:Break when a variable is assigned some value 【发布时间】:2011-01-17 17:14:48 【问题描述】:我希望 jdb(我通过 Eclipse 调试器使用)在。 我对在某个特定行设置断点不感兴趣,而是更一般地设置断点。
例如,每次 x == null 时都中断。
这样的事情可以实现吗?
【问题讨论】:
您正在寻找类似于property change listener 的东西,它可以让您检测到特定的更改并捕获堆栈跟踪。我不相信这在任何调试器中都可用,如果原始库开发人员没有将其变成属性,将很难实现。 【参考方案1】:是的,它们被称为观察点,观察点可以有观察表达式。
根据版本等,您可以通过在大纲视图中选择一个变量并右键单击它来执行此操作,或者在变量视图中控制/单击它。
上下文菜单将包含 Add Watch Expression 和 Edit Watch Expression 的选项。
【讨论】:
我一直在玩观察点,但除非我在变量处于范围内时定义观察点,否则它们似乎不会受到打击。我可以定义一个观察点并在观察变量进入范围时启用它吗?有没有办法限定被监视的变量名? 这似乎不允许你只在找到特定值时才中断。【参考方案2】:是的 - 您需要设置一个“条件断点” - 这使您能够在达到应用程序的某个状态时停止程序执行并逐步执行调试器。
因此,假设您想在满足特定条件时跳到执行中的特定点(根据所附图像),您可以按以下方式执行此操作:
打开调试器透视图并选择'BreakPoints'选项卡
在代码文件中添加一个新的 BreakPoint - 在您想观察程序执行的适当位置
然后回到'Breakpoints'选项卡,右键点击新添加的条目,选择'Breakpoint Properties'
设置激活条件
【讨论】:
嗨,Diunk,您的建议不是取决于在特定行号处满足的条件吗?我想要一个更通用的解决方案,无需识别行号。我只想知道什么时候“x”被分配了一些东西,不管分配发生的方法。 嗨,Daniel,您的问题表明每次“x”(变量)被设置为您希望控制流中断的某个值。问题是,在哪里?好吧,如果您考虑一下,“x”必须是实例或局部变量。在这两种情况下,您都会确切地知道要观察源中的哪一行,不是吗? (设置器或本地块范围)。从那时起,您调用查看调用堆栈并回溯。 嗨,Diunk,我实际上是在尝试调试不属于我的库中的问题。该变量受到保护,并且有一个相当大的类型层次结构扩展了定义它的基类。访问可能在很多地方,这就是我想要一个无上下文断点的原因。 thSoft 和 DigitalRoss 的建议似乎是正确的。 嗨 Daniel,感谢您的澄清 - 我误解了您想要观察变量的上下文 :-) 最好的问候,Dinuk【参考方案3】:对不起,在 Eclipse 中没有办法做你想做的事。您需要的是带有断点条件表达式的观察点。它在 Eclipse 中不存在。
你的问题也是具体调试一个库。可能还有其他方法可以实现您所需要的。在论坛上搜索,看看开发者是如何做到这一点的。
【讨论】:
【参考方案4】:您可以与Field Modification Watchpoints 非常接近。它们仅限于放置在对象的字段上(不是局部变量、参数或表达式),并且只要写入字段就会触发它们,但它是 Eclipse 最接近您想要的。
【讨论】:
+1 但请注意:除了仅限于字段(这似乎符合 OP 的要求)之外,它不会在 更改 时触发,而是在 written(即使它是用相同的先前值写入的)。【参考方案5】:编辑:The ticket I've linked in this answer 已被标记为已验证/已修复。它已集成到最新的 Oxygen 版本中,as detailed in the release notes。我将在下面留下我原来的答案,因为它有很多关于 JDI 和 JDT 如何在 Eclipse 中协同工作的有用信息。
我将从您问题的最终答案开始,因此如果您不想阅读详细信息,则无需阅读。基本上,这是可能的,但有很多问题需要首先回答。如果你想跳过那个直接去买票,here you go,但我建议你继续阅读。
Eclipse 使用JDI(该页面的最底部)向 JVM 注册观察点。这是通过创建观察点的EventRequestManager
方法(实现由JVM 本身提供,而不是Eclipse)完成的,即EventRequstManager.createModificationWatchpointRequest
。这些方法唯一接受的是Field
(请注意,这不是反射Field
类)。所以简而言之,Eclipse不能直接通过Java来做。不用担心,Java 也不处理条件断点。这些也是通过 Eclipse 直接实现的,而不是依赖于 Java。然而,有一些注意事项使得条件观察点比条件断点更难实现。
让我们考虑简单的条件断点。为了让它们工作,您需要一个可以在其中执行代码 sn-p 的上下文。如果没有代码的执行上下文,我们无法评估 sn-p 中的表达式/语句,因为我们无法解析变量、值、类型等。这是使用处理 Java 的 AST 解析器完成的代码转化为实际指令。请记住,您可以在条件中键入多个语句,而不仅仅是单个表达式。然后,求值器在解析表达式后使用上下文(特别是 IJavaStackFrame
)对表达式本身求值。
现在考虑一个条件观察点,因为最后一点非常重要。什么是观察点的执行上下文?变量访问不仅可以发生在同一个类中,还可以发生在其他类中(想想protected
和包成员),也可以发生在内部类中(通过MyClass.this.myField
)。这意味着:
-
局部变量永远不会一致,因为可以通过多种方法访问该字段,
调用访问的类的成员变量永远不会一致,因为可以从多个类访问该字段,
由于与 (2) 相同的原因,在执行上下文中可用的导入类永远不会一致,并且
字段本身的访问永远不会一致,因为它可能需要使用实例、类名、
super
或 MyClass.this.myField
之类的东西(用于内部类访问)进行限定。
这种功能的可行性是有限的。您将很难实际评估观察点的不变条件语句,因为执行上下文中绝对没有任何内容是一致的。这意味着如果没有对代码段应用特殊含义,则代码无法轻松解析和解释,例如:
myField
始终与this.myField
或super.myField
或MyClass.myField
或MyClass.this.myField
相同,具体取决于访问字段的位置。
这使事情变得相当复杂,尤其是在一个已经相对复杂的系统中。条件断点代码的示例可以在here 中找到(使用Ctrl+F 搜索getEvaluationEngine
)。现在接受它并根据一组关于我们在哪里和字段在哪里的规则对表达式添加预处理,并且做事情会变得复杂。
AFAIK,你不能做类似“如果旧/新值是这个,暂停”之类的事情,因为这些信息根本无法从堆栈帧中获得的信息中获得(因此来自调试器)。分配给该值的表达式已按观察点被命中的时间进行评估,但其结果对调试器不可用,因此它对观察点本身的评估器不可用。必须首先执行一个步骤来执行分配,然后必须在该步骤之后评估表达式。这将是非常混乱的,老实说,相当老实。
无论如何,如果您想表达对此功能的支持,您可以使用this Eclipse ticket。然而,它自 2005 年以来(截至目前 8 年)就已经存在,并且社区的支持有限。 TBH,我认为它不会走得太远,尤其是没有更多地澄清这种功能请求背后的期望,也没有首先考虑一些主要的设计考虑。
【讨论】:
正是我所希望的那种答案。谢谢你。我不确定我是否会投赞成票,我同意这听起来很复杂,但它不应该很复杂,所以我想下一个问题是 Java 错误报告在哪里。 (但这是一个完全没有意义的问题,除非你为 Oracle 工作,因为社区投票对当前的 Java 维护者来说价值低于零) @mjaggard 更糟糕的是,实际的 Oracle 错误数据库是私有的,只有在支付 Oracle 支持合同后才能访问它。不过 OpenJDK 错误数据库是开放的。 开放+在我看来毫无意义。以上是关于为变量分配某个值时中断的主要内容,如果未能解决你的问题,请参考以下文章