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:
- the local variables are never consistent since the field can be accessed from multiple methods,
- the member variables of the class from which access is invoked are never consistent since the field can be accessed from multiple classes,
- the imported classes that are available in the execution context are never consistent for the same reason as (2), and
- 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.