Альтернатива программному обеспечению, такому как VisualVM, для программного поиска значений запущенных java-приложений и т. д. путем поиска дампов кучи?

У меня нет опыта работы с java-приложениями, но я обнаружил, что поиск статических указателей и т. д. на адреса памяти этих приложений часто (почти) невозможен, по-видимому, из-за движка java, который обрабатывает код (исправьте меня, если этот способ именования его неправильно, пожалуйста).

Теперь я использовал VisualVM (https://visualvm.dev.java.net/) и это здорово. Я могу выбрать свой Java-процесс и создать дамп кучи. Затем он показывает мне все классы и их значения.

Могу ли я использовать этот метод для непрерывного опроса дампа кучи и получения значений объектов, например, X, Y и Z в игре? Как я буду программно взаимодействовать с таким приложением, и если это не должно быть сделано с помощью VisualVM, что может быть альтернативой?

Редактировать: вот что мне нужно сделать: мне нужно найти все классы со свойствами, имеющими определенное значение. Например: я бы искал координату X (поплавок), и он должен возвращать класс «PlayerCoordsHandler» (просто пример) и соответствующий поплавок с его значением... или, альтернативно, просто способ снова найти тот же самый поплавок. (например, после перезагрузки). Этот процесс не обязательно должен быть программным, поскольку запрос значения уже известного свойства (x float) может быть получен программно (например, с помощью утилиты командной строки или чтения из файла).

Edit2: целевое приложение представляет собой исполняемый файл Windows (но созданный с помощью Java) и запускает собственную виртуальную машину Java. Невозможно добавить параметры Java для отладки. Это, похоже, не требуется, поскольку VirtualVM может отлично отлаживать процесс. Кто-нибудь знает, как?

Заранее спасибо.


person Tom    schedule 07.01.2010    source источник
comment
Это сумасшествие, люди читают VisualVM и просто прыгают со своим YourKit, MAT, мой лучше вашего и т. д., не отвечая на реальный вопрос. Том, не могли бы вы уточнить, что вы пытаетесь сделать, я действительно не думаю, что создание дампов кучи - это путь.   -  person Pascal Thivent    schedule 07.01.2010
comment
@Pascal: Мое упоминание MAT было просто общей альтернативой, как вы можете видеть, и некоторые другие также предполагают, что Том создает MBean или что-то еще, где он может либо публиковать значения как атрибуты, либо иметь операцию для поиска конкретных значений, если это является более практичным. Что тут такого сумасшедшего? Альтернативой, конечно, может быть не использование JMX, а создание другого интерфейса, делающего то же самое, но тогда Тому придется написать много вещей, о которых JMX заботится в любом случае. Он попросил альтернативы для очень смутной потребности, и он их получил. В этом нет ничего сумасшедшего.   -  person Fredrik    schedule 07.01.2010
comment
Все ответы до сих пор были более чем полезными! Я понимаю, что мой вопрос может быть довольно расплывчатым, но для тех, кто не знаком со всеми терминами в этой области, это лучшее, что я могу сделать.   -  person Tom    schedule 07.01.2010
comment
@Tom: Это набор четко определенных параметров, на которые вы хотите взглянуть, или что-то более сложное?   -  person Fredrik    schedule 07.01.2010
comment
Я обновил свой вопрос с примером того, что мне нужно сделать. Я думаю, что это четко определенный параметр (?)   -  person Tom    schedule 07.01.2010
comment
@Tom: я немного отредактировал свой пост. У SO не очень хорошая функция PM, но если я забуду расширить ее, пожалуйста, прокомментируйте этот пост, чтобы напомнить мне.   -  person Fredrik    schedule 07.01.2010
comment
Спасибо, я прокомментировал ваш пост.   -  person Tom    schedule 07.01.2010


Ответы (7)


Похоже, вы хотите отлаживать запущенные Java-приложения.

«Официальным» отладчиком Java является JDB. Я считаю, что это часть JDK. Он имеет возможность устанавливать точки останова, проверять кучи, перечислять и отображать и даже изменять переменные, показывать запущенные потоки и так далее. Обычный отладчик. Но это командная строка, что делает работу с ней головной болью.

Вместо этого имеет смысл использовать IDE со встроенным отладчиком. Я использую Эклипс. Вы можете выполнять все обычные действия по отладке, включая отображение окон с переменными. Вы можете установить условные точки останова и многое другое. В частности, в ответ на ваш вопрос вы можете настроить выражения наблюдения, которые будут оцениваться во время выполнения программы, а их отображения будут обновляться новыми значениями при их изменении.

Вы можете не захотеть запускать свое Java-приложение внутри IDE; или он может работать на сервере веб-приложений. Это не проблема для JDB или Eclipse (или других IDE, таких как NetBeans или IntelliJ Idea): они могут подключаться к работающей JVM и выполнять удаленную отладку с тем же уровнем удобства.

Программа, отлаживаемая таким образом, удаленно или иным образом, работает несколько медленнее, чем если бы она не отлаживалась. Ваша игра во время отладки будет работать с довольно плохим FPS; но он по-прежнему должен более или менее нормально реагировать на взаимодействие с игровым процессом.


Удаленная отладка:

Чтобы иметь возможность подключить отладчик EclipseNetBeans к запущенному процессу Java, вам необходимо запустить этот процесс со следующими параметрами Java…

-Xdebug -Xrunjdwp:transport=dt_socket,address=3704,server=y,suspend=n
person Carl Smotricz    schedule 07.01.2010
comment
Хорошо, похоже, что я не должен использовать дампы кучи, но использовать эти инструменты отладки для прямого доступа к значениям. Попробую сделать это с предложенными приложениями. Есть ли способ автоматизировать это и получить вывод из командной строки или текстового файла? - person Tom; 07.01.2010
comment
Да. Поскольку JDP - это утилита командной строки, считывающая команды со стандартного ввода, я думаю, вы сможете автоматизировать ее работу. Хотя у меня нет никакого опыта в этом. - person Carl Smotricz; 07.01.2010
comment
Обновление: для требования, указанного в обновлении вашего вопроса, вам может понадобиться программная помощь. т. е. если бы вы могли настроить статический или, по крайней мере, уникальный объект внутри вашего игрового кода, который знает, как найти те другие объекты, которые вы ищете, а затем иметь ссылки на них в своих собственных полях, тогда часть отладки задачи будет намного, намного проще. - person Carl Smotricz; 07.01.2010
comment
Я прочитал на java.sun.com/j2se/1.3/docs /tooldocs/solaris/jdb.html : еще один способ использования jdb — подключить его к уже запущенной виртуальной машине Java. ВМ, которую нужно отлаживать с помощью jdb, нужно запускать со следующими параметрами: ... Приложение не запускается с этими параметрами и я тоже не могу этого сделать. Это проблема? - person Tom; 07.01.2010
comment
Обновление @ Карла: к сожалению, у меня нет доступа к исходному коду приложения. - person Tom; 07.01.2010
comment
Только что попробовал отладку с помощью NetBeans. Он возвращает: Присоединение к pid=3704 Не отлаживает или не ожидает подключения отладчика. Это действительно не отладчик, и я не могу установить его, если у меня нет исходного кода, верно? Как VisualVM удается отлаживать его независимо? - person Tom; 07.01.2010
comment
Привет, Карл, боюсь, ты пропустил Приложение не запускается с этими параметрами, и я не могу этого сделать ни в том, ни в другом случае. Я не запускаю это приложение вручную, на самом деле это исполняемый файл Windows с использованием C++, java и других вещей вместе взятых. С VisualVM я могу просто выбрать процесс, и он выполнит свою работу без добавления каких-либо параметров. - person Tom; 07.01.2010
comment
Ага, понятно. Это начинает выглядеть нетривиально. Вероятно, вы все еще могли бы обмануть его, удалив настоящий java из пути к классам и заменив его на java.cmd или java.bat, которые вызывают настоящий с требуемыми параметрами. Но если это не сработает, боюсь, пришло время отказаться от этого подхода. :( - person Carl Smotricz; 07.01.2010
comment
Прошу прощения, что не упомянул об этом раньше. Не думал, что это актуально, потому что VirtualVM может просто отлаживать приложение. Жаль, что он создает только дампы кучи. Может быть, поэтому. Боюсь, я понятия не имею, как обмануть его так, как вы предлагаете. Спасибо большое за помощь. - person Tom; 07.01.2010
comment
Сделайте серьезную попытку запустить поддельную Java. Я только что вспомнил, что можно из командной строки внедрить класс запуска из-за пределов Java-программы, и если бы это можно было сделать, это открыло бы дверь для всех видов извращенных помощников по отладке. - person Carl Smotricz; 07.01.2010
comment
Однако я не вижу никаких java-файлов (все они связаны с .exe, поэтому не принимают никаких конкретных параметров java). Я знаю расположение JRE, которое использует приложение. Это поможет? - person Tom; 07.01.2010
comment
Да. Я очень надеюсь, что не трачу ваше время на погоню за дикими гусями. Идея состоит в том, чтобы удалить эти JRE java.exe и javaw.exe из системного PATH (вы можете просто переименовать их, если хотите быть жестоким) и поместить файлы java.CMD и javaw.CMD в путь, который будет вызывать переименованные java exe под новым именем. Если вы можете заставить это работать, у вас есть Java на хвосте. Я продолжаю упоминать как java.exe, так и javaw.exe, потому что ваше приложение может использовать любой из них. Javaw обычно предназначен для приложений с графическим интерфейсом. - person Carl Smotricz; 07.01.2010
comment
Ну, приложение вызывает java.exe, а не java.CMD. Я не могу изменить его, чтобы вызывать java.CMD вместо java.exe, верно? - person Tom; 07.01.2010
comment
Обновление: кажется, что java.exe и javaw.exe вообще не используются, так как игра работает нормально после их удаления. Однако Java.dll используется, не уверен насчет других файлов. - person Tom; 07.01.2010
comment
Update2: также используется client/jvm.dll. Как можно обрабатывать параметры JVM, если она не запускается исполняемым файлом, а загружается в приложение с DLL? - person Tom; 07.01.2010
comment
Честный ответ: я не в себе и сдаюсь. Извиняюсь! - person Carl Smotricz; 07.01.2010
comment
Без проблем. :P Я тоже на этом этапе. Спасибо за помощь. - person Tom; 07.01.2010

Взгляните на YourKit. Вы можете отслеживать ЦП, память и потоки в реальном времени и создавать дампы, когда захотите. Он даже может сравнивать разные дампы памяти, чтобы показать вам, какие объекты были добавлены/удалены.

Однако это не бесплатно, у него есть 15-дневный (или 30-дневный?) полнофункциональный ознакомительный период. Если бесплатность не является реальной проблемой, это определенно отличный инструмент.

person extraneon    schedule 07.01.2010

Хорошей отправной точкой является jps и Инструменты jstat добавлены в Java 6 (i считать). jps дает вам pid и основной класс для каждого приложения. jstat дать вам более подробную информацию о процессе

person n002213f    schedule 07.01.2010

Запуск дампа кучи полезен для пост-мортемного анализа, например, утечек памяти, но поскольку сборщик мусора Java перемещает объекты, вы не можете использовать значения памяти дампа кучи для надежного доступа к этим объектам.

Если вам нужен способ запрашивать внутренние значения извне приложения, вы можете изучить настройку API службы RMI, с помощью которого вы сможете получать нужные вам значения.

Другой метод (если вам просто нужно что-то протестировать) может заключаться в подключении к процессу через API отладки Java.

Если вы знаете используемое местоположение JRE, вы можете переименовать java.exe и написать оболочку (C/C++), которая добавляет параметры отладки, перечисленные Карлом, и, в свою очередь, вызывает named_java.exe.

Другой возможностью может быть добавление или обновление классов в файле .jar приложения. Для этого вам не нужен источник.

Том, ты пытаешься перепроектировать приложение, которое специально пытается запутать его работу? Если да, то вы могли бы пойти дальше, если связались с производителем и спросили его, какие возможности они видят для того, чего вы пытаетесь достичь?

person rsp    schedule 07.01.2010
comment
Просто чтобы помочь Тому и мне следить за тем, какие решения находятся в работе: я боюсь, что недавние его обновления сделали невозможным RMI (нет источника, с которым можно было бы возиться) и удаленную отладку (вероятно) тоже (нет доступа к Командная строка JVM). - person Carl Smotricz; 07.01.2010
comment
К сожалению, приложение работает нормально, когда java-exe удалены. Также нет активного процесса Java, и я не могу найти службу Java. Однако используется файл java.dll в папке JRE, и VisualVM может видеть приложение. Он также проверяет правильность расположения моей папки JRE, просто похоже, что он не использует исполняемые файлы Java. - person Tom; 07.01.2010

Вы можете легко создать дамп кучи, создав собственное соединение JMX с JVM, как это делает VisualVM. Анализ дампа кучи очень возможен (данные есть и полностью отключены от JVM, поэтому сборщик мусора не мешает).

Однако, если это не очень конкретный сценарий, который вы ищете, вам, вероятно, будет гораздо лучше предоставить heapdump MAT и найти там хороший рабочий процесс.

Редактировать. В этом конкретном случае, вероятно, лучше создать какой-то конкретный API для доступа к значениям извне (и, возможно, опубликовать значения как MBeans с использованием JMX). Создание дампа кучи требует много работы, если все, что вы хотите сделать, это отслеживать несколько значений.

Edit2: Основываясь на ваших изменениях, мне кажется, что вы действительно могли бы извлечь выгоду из публикации собственного MBean поверх JMX. Мне нужно бежать на встречу, но, если кто-то другой не сделает это, пока меня нет, я постараюсь не забыть дать вам несколько советов позже. Либо в редактировании этого, либо в новом посте.

person Fredrik    schedule 07.01.2010
comment
Это было бы здорово. Я действительно хочу только контролировать значения. Я был бы признателен за помощь в том, как использовать подход MBean через JMX для получения значений извне приложения, подключенного к JVM. - person Tom; 07.01.2010
comment
С извне я имею в виду, что это не мое приложение, но все же на той же системе, конечно. Мне не нужно обращаться к другому удаленному соединению или чему-то еще, если именно поэтому вы хотите использовать JMX. Если нет, проигнорируйте это сообщение. - person Tom; 07.01.2010
comment
@ Том, дай мне посмотреть, правильно ли я понял. Приложение, которое вы хотите контролировать, не принадлежит вам, но вы все же достаточно знаете о его внутренней работе, чтобы смотреть на значения переменных? Это вполне выполнимо, даже если это не ваше приложение, но мне интересно, стоит ли это усилий. - person Fredrik; 07.01.2010
comment
Я думаю, вы правильно поняли. Например, в игре всегда будет объект игрока (большинство из них). Можно получить параметры координат (значения) этого объекта из JVM и использовать их для автоматизации вещей в игре. Мне просто нужно иметь возможность искать значения, а затем постоянно получать доступ к значениям этого объекта. Глядя на возможности VisualVM, это кажется возможным. Обычно для адресов памяти используются статические указатели. Однако из-за JVM это не представляется возможным. - person Tom; 07.01.2010

Если вы хотите опросить значения определенных объектов во время работы вашего приложения Java, вы, вероятно, обнаружите, что с помощью JMX — это лучший и более эффективный подход, чем использование дампа кучи. С помощью JMX вы можете определить, какие значения следует отображать, и использовать такие инструменты, как VisualVM или JConsole, для их просмотра во время выполнения.

person Mark    schedule 07.01.2010
comment
Я не уверен. Зависит от того, есть ли у приложения доступный API для доступа к тому, что вам нужно. Я думаю, вы могли бы создать MBeans для вызова API, но могут возникнуть проблемы с регистрацией MBeans при запуске. Вам, вероятно, потребуется создать свой собственный код Java, чтобы сделать это, а затем запустить существующее приложение. Опять же, понятия не имею, возможно ли это, не зная, с чем ему приходится работать. - person Mark; 07.01.2010

С помощью VisualVM и heapdump вы можете найти все классы с определенным свойством по OQL:

var out = "";
var cls = filter(heap.classes(), "/java./(it.name)")

while (cls.hasNext()) {
  var cl = cls.next();
  var fls = cl.fields;
  while (fls.hasMoreElements()) {
    var fl = fls.nextElement();
    if (/size/(fl.name)) {
      out = toHtml(cl) + "." + fl.name + "()\n";
    }
  }
}

out.toString()

и напишите собственный журнал для BTrace.

Это альтернатива для отладки.

person gavenkoa    schedule 07.07.2014