4

JDWP と JVMTI を使用して、実行中の Java アプリケーションの情報を取得するアプリケーションを開発しています。Sun Java には JDWP のリファレンス実装が付属しているため、agentlib -jdwp: を使用するとリファレンス実装が使用されます。私たちの目的は、JVMTI を研究し、JVMTI エージェントを作成して特定の詳細を取得することです。また、ユーザーが実行中の Java アプリケーションに関する特定の情報を要求できるフロント エンドを作成します。このためには、JDWP の実装を作成する必要があります。JVMTI エージェントを作成し、それを使用してコマンド ラインから Java アプリケーションにアタッチすることはできましたが。しかし、私たちの目的は、この情報を別の Java プロセス (フロント エンド) に送信することです。

したがって、JVMTI エージェント (バックエンド) からの情報を照会するフロント エンドの Java アプリケーションがあります。これらのエージェントは、動的に検査する実行中の Java アプリケーションに接続できる必要があります。これを行う方法についてのアイデアはありますか?または、誰かがこれを以前に試したことがありますか?

4

1 に答える 1

6

JDK には、リモート/ローカル デバッグ用の Java API が組み込まれています ( com.sun.jdi. )。

API の使用をすぐに開始するには、$JDK_DIR\demo\jpda\examples.jarの例を参照してください。【詳細


公式の例はあまり明確ではないため、再利用可能な例を次に示します (このブログ投稿に触発されています):

VMAcquirer.java (接続マネージャー)

public class VMAcquirer {

    public VirtualMachine connect(String host,int port) throws IOException {
        String strPort = Integer.toString(port);
        AttachingConnector connector = getConnector();
        try {
            VirtualMachine vm = connect(connector,host, strPort);
            return vm;
        } catch (IllegalConnectorArgumentsException e) {
            throw new IllegalStateException(e);
        }
    }

    private AttachingConnector getConnector() {
        VirtualMachineManager vmManager = Bootstrap.virtualMachineManager();

        for (Connector connector : vmManager.attachingConnectors()) {
            if("com.sun.jdi.SocketAttach".equals(connector.name()))
                return (AttachingConnector) connector;
        }
        throw new IllegalStateException();
    }

    private VirtualMachine connect(AttachingConnector connector,String host,String port)
            throws IllegalConnectorArgumentsException, IOException {

        Map<String, Connector.Argument> args = connector.defaultArguments();
        Connector.Argument portArg = args.get("port");
        portArg.setValue(port);
        Connector.Argument addressArg = args.get("hostname");
        addressArg.setValue(host);

        return connector.attach(args);
    }
}

Monitor.java (実際の監視)

class Monitor {
    public static void main(String[] args){
        VirtualMachine vm = new VMAcquirer().connect("192.168.0.x", 2600);

        System.out.println("name="+vm.name()); //Info about the remote VM
        System.out.println("description="+vm.description());

        EventRequestManager erm = vm.eventRequestManager();
        [...] //Send request using erm instance

        loopEventQueue(vm); //Start a loop to listen to the events received
    }

    public static void loopEventQueue(VirtualMachine vm) throws InterruptedException {
        EventQueue eventQueue = vm.eventQueue();
        while (true) {
            EventSet eventSet = eventQueue.remove();
            for (Event ev : eventSet) {
                if(ev instanceof MethodEntryEvent) {
                    handleMethodEntryEvent(ev);
                }
                [...]
            }
        }
    }
}

監視対象のアプリケーションで必要

java -Xdebug -Xrunjdwp:transport=dt_socket,address=2600,server=y,suspend=n ...

JDWPで入手できる情報

  • メソッドの呼び出しと戻りのトレース (おそらくプロファイリングまたはロギングを行うため)
  • フィールド値の変更
  • VM 情報 (例の name() と description() を参照)
  • 式を評価して任意のコードを実行する

  • 于 2011-06-25T03:59:40.123 に答える