プログラムの実行中に変数値の変化を監視できるようにする方法があるかどうかを知りたいです。もちろん、デバッガーは使用しません。プログラムで実行したいと思います。例えば:
class A
{
public static int valueToBeWatched;
}
したがって、実行時に、プロジェクト内の任意のクラスのいずれかのメソッドが変更された場合、この値MyValueChangeListner
イベントが呼び出される必要があります。
プログラムの実行中に変数値の変化を監視できるようにする方法があるかどうかを知りたいです。もちろん、デバッガーは使用しません。プログラムで実行したいと思います。例えば:
class A
{
public static int valueToBeWatched;
}
したがって、実行時に、プロジェクト内の任意のクラスのいずれかのメソッドが変更された場合、この値MyValueChangeListner
イベントが呼び出される必要があります。
それはいけません。Java自体に組み込まれている変更監視フックはありません。もちろん、ポーリングは可能です。しかし、それでは「ライブ」にはなりません。
AspectJはそのような考えを可能にするかもしれませんが、それがプリミティブ変数に当てはまるのか、それともゲッターとセッターを使用している場合にのみ当てはまるのかはわかりません。
クリーンなJavaの方法は、変数を作成し、private
ゲッターとセッターを使用することです。
private valueToBeWatched;
public void setValue(int newval) {
valueToBeWatched = newval;
notifyWatchers();
}
public int getValue() {
return valueToBeWatched;
}
static
ちなみに、可能な限り避けてください。特にpublic
ですが、そうではありませんfinal
。
int
タイプを、値が変更されるたびにリスナーを呼び出すクラスに置き換える必要があります。実際に変更されていない場合は、値の設定を無視することをお勧めします。
例えば
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;
}
この置換はバイトコードインジェクションを使用して実行できますが、元のコードを変更するのは非常に簡単です。
別の方法は、値を監視して定期的に変更を探すことです。値の変化が非常に遅い場合を除いて、すべての変化が見られるとは限りません。Debugger APIを使用してこれを行うことはできますが、それは単純ではなく、APIに精通している場合を除いて、使用することはお勧めしません。
JavaDebuggerAPIリンク
http://java.sun.com/javase/technologies/core/toolsapis/jpda/
Oracleの最新のJavaSEJDKを使用できる場合は、javafx.beans.propertyおよびjavafx.beans.valueAPIを使用することをお勧めします。
ここにいくつかの基本的なコードがあります:
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);
}
}
}
出力は次のとおりです。
値が9.0から3.0に変更されました
値が3.0から6.0に変更されました
前述のように、この質問は、提供されたフィールドの変更をリッスンするエージェントを作成することで解決できます(fieldWatchを参照)。エージェントは、C呼び出しと互換性のある言語を使用してコンパイルし、-agentpath:<path-to-agent>=<options>
スイッチを使用してVMで呼び出す必要があります。
より高いレベルのオプションは、JPDA / JDIを使用して実行中のプロセスにアタッチすることです。これは、上記の呼び出しを(Java)ModificationWatchpointEventでラップします。