Использование JDWP и JVMTI для получения информации о запущенном приложении Java - PullRequest
4 голосов
/ 17 декабря 2009

Мы разрабатываем приложение для получения информации о работающем Java-приложении с использованием JDWP и JVMTI. Sun Java поставляется с эталонной реализацией JDWP, поэтому при использовании agentlib -jdwp: будет использоваться эталонная реализация. Наша цель - изучить JVMTI и написать агентов JVMTI, чтобы получить конкретные детали. Также создание внешнего интерфейса, с помощью которого пользователь может запросить конкретную информацию о работающем Java-приложении. Для этого нам нужно написать нашу реализацию для JDWP. Хотя мы смогли написать JVMTI-агенты и использовать их для подключения к Java-приложению из командной строки. Но наша цель - отправить эту информацию другому Java-процессу (Front End).

Итак, у нас есть Java-приложение - интерфейс, запрашивающий информацию у агентов JVMTI (Back-End). Эти агенты должны иметь возможность подключаться к работающему Java-приложению, которое мы собираемся проверять динамически. Любые идеи о том, как это можно сделать? Или кто-нибудь пробовал это раньше?

1 Ответ

6 голосов
/ 25 июня 2011

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 () в примере) Оценить выражение для выполнения произвольного кода
...