42

I want jdb (which I'm using via the Eclipse debugger) to break when a variable is assigned some value. I'm not interested in setting a breakpoint at some specific line but rather more generally.

For example, break every time x == null.

Is such a thing achievable?

Daniel
  • 499
  • 1
  • 4
  • 6
  • What you're looking for is something like a [property change listener](http://docs.oracle.com/javase/tutorial/uiswing/events/propertychangelistener.html) that would let you detect a specific change and capture the stack trace. I don't believe this is available in any debugger yet, and it will be difficult to implement if the original library developers didn't make it into a property. – Cebence Apr 30 '13 at 12:51

5 Answers5

41

Yes - What you need to setup is a 'Conditional Breakpoint' - this gives you the ability to stop the program execution and step through the debugger when a certain state of the application is reached.

So, let's say you want to jump into a particular point in the execution when a certain condition is fulfilled (as per the image attached), you can do this as follows:

1.

Open your debugger perspective and select the 'BreakPoints' tab

  1. Add a new BreakPoint in the code file - at the appropriate place where you would like to observe the program execution

  2. Then go back to the 'Breakpoints' tab, right-click on the newly added entry, and select 'Breakpoint Properties'

  3. Set the condition upon which it should be activated

alt text
(source: ibm.com)

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Dinuk
  • 1,506
  • 3
  • 16
  • 22
  • 8
    Hi Diunk, Isn't your suggestion is dependent on the condition being satisfied at a particular line number? I'd like a more general solution that obivates the need to identify line numbers. I just want to know when "x" is assigned something, irrespective of the method in which the assignment takes place. – Daniel Mar 04 '10 at 06:37
  • Hi Daniel, Your questions states everytime "x" (a variable) gets set a certain value you want the control flow to break . Questions is, where? Well, if you think about it, "x" has to be an instance or local variable. In both contexts you would know exactly which line in your source you would want to observe ,wouldn't you? (the setter, or the local block scope). From that point, you call look at the call stack and backtrack. – Dinuk Mar 04 '10 at 07:24
  • 5
    Hi Diunk, I was actually trying to debug an issue in a library that isn't mine. The variable is protected and there is a reasonably large type hierarchy extending the base class where it is defined. The access could be in lots of places which is why I wanted a context-free breakpoint. It seems like thSoft and DigitalRoss are correct in their suggestion. – Daniel Mar 04 '10 at 23:01
  • Hi Daniel, Thanks for clarifying - I misunderstood the context in which you wanted to observe the variable :-) Best regards, Dinuk – Dinuk Mar 07 '10 at 15:36
10

You can come pretty close with Field Modification Watchpoints. They are limited to being placed on fields of objects (not local variables, parameters, or expressions) and they are triggered whenever the field is written to, but it's the closest Eclipse has to what you want.

Old Pro
  • 24,624
  • 7
  • 58
  • 106
  • +1 But notice: besides being restricted to fields (which seems to be ok with the OP's requirement), it will trigger not exactly when it _changes_ but when it's _written_ (even when it's written with the same previous value). – leonbloy Apr 30 '13 at 14:34
9

Edit: The ticket I've linked in this answer has been marked verified/fixed. It has been integrated into the latest Oxygen release, as detailed in the release notes. I'll leave my original answer below since it has a lot of useful information regarding how JDI and JDT work together in Eclipse.


I'm going to start with the final answer to your question so you don't have to read the details if you don't want to. Basically, this is kind of possible but with a lot of questions that have to be answered first. If you want to skip that and go straight to the ticket, here you go, but I recommend you read on.

Eclipse uses JDI (very bottom of that page) to register watchpoints with the JVM. This is done through the EventRequestManager methods (the implementation is provided by the JVM itself, not Eclipse) that create watchpoints, i.e. EventRequstManager.createModificationWatchpointRequest. The only thing that these methods accept is a Field (note that this isn't the reflective Field class). So in short, Eclipse can't do it directly through Java. Never fear, Java doesn't handle conditional breakpoints either. Those are also implemented through Eclipse directly instead of relying on Java. There are, however, some caveats that make conditional watchpoints much more difficult to implement than conditional breakpoints.

Let's consider plain, conditional breakpoints. In order for them to work, you need a context in which you can execute the code snippet. Without an execution context for the code, we can't evaluate the expression/statements in the snippet since we have no way of resolving variables, values, types, etc. This is done using an AST parser that processes the Java code into actual instructions. Remember that you can type a number of statements into a condition, not just a single expression. The evaluator then uses a context (specifically, an IJavaStackFrame) to evaluate the expression itself after parsing it.

Now think about a conditional watchpoint, because that last point is very important. What is a watchpoint's execution context? Variable access can happen not only within the same class, but also in other classes (think protected and package members), and in inner classes as well (via MyClass.this.myField). This means that:

  1. the local variables are never consistent since the field can be accessed from multiple methods,
  2. the member variables of the class from which access is invoked are never consistent since the field can be accessed from multiple classes,
  3. the imported classes that are available in the execution context are never consistent for the same reason as (2), and
  4. the access of the field itself is never consistent since it may require qualification with an instance, class name, super or with something like MyClass.this.myField (for inner class access).

The feasibility of such a feature is kind of limited. You'd be hard-pressed to actually evaluate a non-changing conditional statement for a watchpoint since absolutely nothing in the execution context is going to be consistent. This means that the code cannot be easily parsed and interpreted without special meaning applied to pieces of the code, such as:

myField is always the same as this.myField or super.myField or MyClass.myField or MyClass.this.myField, depending on where the field is being accessed.

This complicates things quite a bit, especially in a system that is already relatively complex. An example of the conditional breakpoint code can be found here (search for getEvaluationEngine using Ctrl+F). Now take that and add in pre-processing on the expression based on a set of rules about where we are and where the field is, and doing things can get complicated.

AFAIK, you can't do something like, "if the old/new value is this, suspend", because that information simply isn't available from the information you can get in the stack frame (and thus from the debugger). The expression being assigned to the value has been evaluated by time the watchpoint is hit, but its result isn't available to the debugger, therefore it isn't available to an evaluator on the watchpoint itself. A step would have to be performed first to perform the assignment, then the expression would have to be evaluated after the step. It'd be horribly messy, and honestly, rather hacky at that.

In any case, if you want to voice your support for this feature, you can use this Eclipse ticket. However, it's been around since 2005 (8 years as of now) and has limited support from the community. TBH, I don't see it going very far, especially without more clarification of the expectations behind this kind of a feature request and without some major design consideration put behind it first.

Brian
  • 17,079
  • 6
  • 43
  • 66
  • Exactly the kind of answer I was hoping for. Thank you. I'm not sure whether I'll vote for it or not, I agree it sounds very complex but it shouldn't be complex so I guess the next question is where the Java bug report is. (But that's a completely and utterly pointless question unless you work for Oracle because community votes are worth less than zero to the current Java maintainers) – mjaggard May 01 '13 at 08:37
  • @mjaggard Even worse is the actual Oracle bug database is private, and you can only access it if you pay for an Oracle support contract. The OpenJDK bug database is open though. – Brian May 01 '13 at 21:50
  • Open + meaningless as far as I can see. – mjaggard May 02 '13 at 10:52
5

Yes, those are called watchpoints, and watchpoints can have watch expressions.

Depending on versions and such, you do this by selecting a variable in the Outline view and right-clicking on it, or in the Variables view, control/click on it.

A context menu will have choices for Add Watch Expression and Edit Watch Expression.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • I've been playing around with watchpoints but they don't seem to get hit unless I define the watchpoint when the variable is in scope. Can I define a watchpoint and have it enable when the watched variable comes into scope? Is there a way to qualify the watched variable names? – Daniel Feb 17 '10 at 05:57
  • This doesn't seem to let you only break when a specific value is found. – mjaggard Apr 24 '13 at 10:27
1

Sorry, but there is no way to do what you want in Eclipse. What you need is a watchpoints with the conditional expression of a breakpoint. It does not exist in Eclipse.

Your problem is also specific debug a library. There are probably other ways to achieve what you need. Search over forum to see how developers do that.

mki
  • 635
  • 3
  • 10