Dangling Piyush
Dangling Piyush

Reputation: 3676

How to watch a variable for changes

I want to know if there's any way so I could watch for variable value change when the program is running. Of course not using debugger I wanna do it Programmatically. For example:

class A
{
   public static int valueToBeWatched;
}

So at runtime if in any method of any class in my project modifies this value MyValueChangeListner event should get called.

Upvotes: 8

Views: 24481

Answers (4)

onebeartoe
onebeartoe

Reputation: 145

If you can use the latest Java SE JDK from Oracle, then I suggest using the javafx.beans.property and javafx.beans.value APIs.

Here is some basic code:

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;

public class ObservableValues
{        

    public static void main(String[] args) 
    {
        DoubleProperty dp = new SimpleDoubleProperty(9);
        dp.addListener( new DoubleChangeListener() );
        dp.setValue(3);
        dp.setValue(6);
    }

    static class DoubleChangeListener implements ChangeListener<Number>
    {
        @Override
        public void changed(ObservableValue<? extends Number> ov, Number oldValue, Number newValue) 
        {
            System.out.println("the value has changed from " + oldValue + " to " + newValue);
        }
    }

}

Here is the output:

the value has changed from 9.0 to 3.0

the value has changed from 3.0 to 6.0

Upvotes: 5

tucuxi
tucuxi

Reputation: 17945

The question, as stated, can be solved by writing an Agent to listen to changes on the provided field (see fieldWatch). The Agent would have to be compiled using a C-calling-compatible language, and invoked on VM start with an -agentpath:<path-to-agent>=<options> switch.

A higher-level option is to attach to a running process using JPDA/JDI, which wraps the above call in a (Java) ModificationWatchpointEvent.

Upvotes: 1

Peter Lawrey
Peter Lawrey

Reputation: 533492

You need to replace the type int with a class which will invoke your listener whenever the values changes. You might like to ignore setting the value when it hasn't actually changed.

e.g.

 private int value;
 private final MyValueChangeListener listener;

 public void setValue(int value) {
    if(this.value == value) return;
    listener.changed(this, this.value, value);
    this.value = value;
 }

You can perform this replace using byte code injection, but it is much simple to change the original code.

An alternative is to monitor the value to look for changes periodically. Unless the value changes very slowly you might not see every change. You can use the Debugger API to do this but it not simple and I wouldn't suggest you use it unless you are familiar with the API already.

Java Debugger API Links

http://java.sun.com/javase/technologies/core/toolsapis/jpda/

http://docs.oracle.com/javase/6/docs/technotes/guides/jpda/

http://docs.oracle.com/javase/6/docs/jdk/api/jpda/jdi/

Upvotes: 9

Has QUIT--Anony-Mousse
Has QUIT--Anony-Mousse

Reputation: 77454

You cannot. There is no watch-on-modification hook built into Java itself. Obviously, you could do polling, though. But then it won't be "live".

AspectJ may allow such a think, but I'm not sure whether it holds for primitive variables, or only when you are using getters and setters.

The clean Java-way is to make the variable private and use getters and setters.

private valueToBeWatched;

public void setValue(int newval) {
  valueToBeWatched = newval;
  notifyWatchers();
}

public int getValue() {
  return valueToBeWatched;
}

On a side note, avoid static whenever possible. In particular public but not final.

Upvotes: 13

Related Questions