Можем ли мы просматривать объекты в памяти JVM? - PullRequest
8 голосов
/ 11 мая 2010

На работе мы обнаружили, что в некоторых случаях (особенно в медленных) у нас другое поведение, приобретенное при перезагрузке.

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

У нас фактически нет регистраторов для активации ... это старый компонент ...

Таким образом, я хотел бы знать, существуют ли инструменты, которые могут помочь нам увидеть различные объекты, присутствующие в памяти JVM, чтобы проверить содержимое кэша ...

Спасибо!

Изменить:

У меня нет прямого доступа к рабочим серверам, наш сервер приложений имеет weblogic 10, у меня нет указателя на объект, но я знаю тип объекта кэша ...

Edit2:

Наши серверы работают на jre 1.5, возможно ли использовать jmap? Не могу найти его в jdk5 :( Кроме того, удаленная отладка может быть хорошей, но мы не можем по соображениям безопасности ...

Edit3:

На самом деле jhat + VisualVM мне подходит, я нашел свой объект в дампе, но не могу правильно прочитать хэш-карту (объект, содержащий около 60000 элементов) ... Есть ли инструмент для удобного чтения таблицы concurrenthashmap? Мне нужно найти значение ключа (или его наличие на карте), не просматривая вручную записи 60 КБ. На самом деле я читал на форуме Eclipse MAT, что это также невозможно с ним ...

Edit4: После некоторого опыта мне действительно нравятся такие инструменты, как VisualVM. Также используется YourKit. Есть несколько полезных функций, таких как OQL, для поиска нужных экземпляров, на которые нужно обратить внимание ...

Ответы [ 3 ]

7 голосов
/ 11 мая 2010

Это в основном, чтобы расширить то, что сказал Уилл. Я добился больших успехов, когда наши администраторы создавали кучу наших производственных систем, хотя с оговоркой, что конкретный сервер, который вы создаете, будет не отвечать на запросы до завершения дампа. Затем получите этот файл и используйте плагин Eclipse MAT, чтобы посмотреть на него. Если вам не нравится Eclipse, можно использовать Netbeans и простой плагин VisualVM. Это может создать несколько больших файлов, хотя, возможно, вам придется работать в 64-битной системе.

4 голосов
/ 11 мая 2010

Довольно просто запустить jmap для вывода COUNT экземпляров объекта, но я не знаю, действительно ли это то, что вас действительно интересует.

Вы также можете использовать jmap для создания дампа кучи всей кучи, и с этим (и jhat) вы можете видеть ОТНОШЕНИЯ ОБЪЕКТА (т. Е. Какой объект указывает на что), но не обязательно объект СОДЕРЖАНИЕ.

Конечно, данные есть в дампе кучи, они не видны "щелчком мыши".

Некоторые из профессиональных профилировщиков, я думаю, позволят вам анализировать объекты в куче дампов.

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

3 голосов
/ 11 мая 2010

У вас есть доступ к дескриптору / указателю на объекты? Если это так, вы можете запустить его в режиме отладки и посмотреть на него в отладчике, таком как Eclipse. Это позволит вам проверять переменные и тому подобное.

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


edit: Как я отметил в своем комментарии, я не знаю способа получить доступ к объекту без какой-либо ссылки или ссылки. Например, инкапсулирован ли объект в другом объекте? Если это так, вы можете сделать что-то вроде следующего:

Class<?> objectClass = myPointer.getClass();
Field[] objectFields = objectClass.getDeclaredFields();
for (Field field : objectFields) {
    field.setAccessible(true);
    //Or whatever you would need to do to get the information you need
    System.out.println(field.get(myPointer).toString());
}

Вы также можете сделать что-то вроде:

Field targetField = objectClass.getDeclaredField("myFieldName");
targetField.setAccessible(true);
MyOldObjectType target = (MyOldObjectType)targetField.get(myPointer);
//do whatever you need to do here

Обратите внимание, что все методы отражения генерируют исключения, поэтому вам придется обрабатывать их соответствующим образом. Кроме того, setAccessible(true) означает, что вы можете получить доступ к закрытым полям и методам объекта. Это ЧРЕЗВЫЧАЙНО ОПАСНЫЙ - Используйте его только в случае крайней необходимости.

...