JMap.java — истекло время ожидания при попытке подключения к серверу отладки — SwDbgSrv.exe

Я пытаюсь запускать и отлаживать утилиты из sun.jvm.hotspot.tools и sun.jvm.hotspot.utilities (например, JMap.java), чтобы лучше понять, что происходит.

К сожалению, я очень рано застреваю со следующим сообщением об ошибке и даже не могу много отлаживать:

Attaching to process ID 5144, please wait...
Error attaching to process: Timed out while attempting to connect to debug server (please start SwDbgSrv.exe)

Похоже, что по какой-то причине инструменты пытаются подключиться к «серверу отладки», работающему на порту 27000.

В документе sun.jvm.hotspot.tools.HeapDumer.java я нашел следующее:

Этот инструмент используется утилитой JDK jmap для создания дампа кучи целевого процесса/ядра в виде двоичного файла HPROF. При необходимости его также можно использовать как отдельный инструмент.

Поэтому я (возможно, наивно) предположил, что jmap.exe каким-то образом использует это, но у меня никогда не было таких проблем при создании дампа кучи с помощью jmap. Мне никогда не нужно было сначала запускать другой процесс.

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

Спасибо


person Haasip Satang    schedule 06.06.2015    source источник


Ответы (1)


sun.jvm.hotspot.* инструменты являются частью агента обслуживания HotSpot.

Я предполагаю, что вы используете JDK 6 в Windows, потому что сервер отладки больше не требуется, начиная с JDK 7. В более ранних версиях вам приходилось запускать SwDbgSrv.exe, чтобы использовать Serviceability Agent.

Некоторые встроенные утилиты JDK (jmap, jstack) имеют два режима выполнения: кооперативный и принудительный. В обычном совместном режиме эти инструменты используют механизм динамического подключения для подключения к целевая виртуальная машина. Затем запрошенная команда выполняется непосредственно целевой виртуальной машиной из целевого процесса.

Принудительный режим (jmap -F, jstack -F) ведет себя совершенно иначе. Инструмент приостанавливает целевой процесс, а затем считывает память процесса с помощью Serviceability Agent. Команда выполняется в процессе инструмента, когда целевая виртуальная машина приостановлена. Это то, что делают sun.jvm.hotspot.* утилиты.

person apangin    schedule 06.06.2015
comment
Интересный ответ, не знал, что были изменения с JDK 6 на 7. На самом деле я до сих пор не понимаю, если честно: 1. У меня нет SwDbgSrv.exe, даже в моей установке JDK 6. 2. Я использую открытые исходные коды JDK 7 (sun.jvm.hotspot.tools.HeapDumper, sun.jvm.hotspot.tools.JMap. и т. д.), и инструменты по-прежнему требуют, чтобы этот сервер был запущен (не знаю, где я могу его получить). Я хотел бы отладить инструменты в Eclipse и, следовательно, попытаться запустить все там, а не выполнять jmap на консоли (извините, если это неясно из вышеизложенного). Есть еще идеи? - person Haasip Satang; 07.06.2015
comment
@HaasipSatang 1. SwDbgSrv.exe не поставляется с JDK. 2. У вас устаревшие исходники. Где ты достал их? здесь представлены последние исходники JDK 7 HotSpot. 3. Вероятно, вам вообще не нужны эти инструменты. Как я уже говорил, вы можете использовать Dynamic Attach для получения дампа потока или дампа кучи. Это очень легко. Посмотрите примеры удобства обслуживания JVM, в частности, demo2. - person apangin; 08.06.2015
comment
Спасибо. У меня действительно была довольно старая версия исходников OpenJDK 7. Но это было 7, а не 6. Так что что-то могло измениться в 7. Поэтому, когда я начал свой проект с OpenJDK и использовал новые исходники для JMap, теперь он подключается, и я могу отлаживать. Однако мне пришлось создать файл sa.properties и использовать sun.jvm.hotspot.runtime.VM.disableVersionCheck=true (поскольку я не знал, какие значения устанавливать). Так что я, очевидно, еще не использую его правильно, но, по крайней мере, пока он работает, и я могу его отлаживать. Просто из любопытства, не знаете ли вы, где я могу найти SwDbgSrv.exe на случай, если он мне когда-нибудь понадобится? - person Haasip Satang; 09.06.2015
comment
@HaasipSatang Если быть точнее, это было изменено в 7u2. Единственный способ получить SwDbgSrv.exe — это, вероятно, собрать его из источники. - person apangin; 09.06.2015
comment
спасибо :) И просто к вашему сведению: я делаю все это не для создания дампа кучи. На самом деле я пытаюсь выяснить, как я могу получить тот же идентификатор объекта, который записан в дампе кучи во время выполнения из объекта. Итак, в основном я хочу создать дамп кучи и в какой-то более поздний момент времени получить идентификатор объекта живого объекта и сравнить его со значениями из дампа кучи. Я думал, что идентификатор был адресом памяти. Но значение, которое я получил с sun.misc.Unsafe, отличается. Вот почему я хотел отладить эти классы, чтобы увидеть, как они получают идентификатор. Как вы думаете, я могу получить это в процессе, а не прикреплять? - person Haasip Satang; 09.06.2015
comment
На самом деле я задал этот вопрос здесь еще до того, как я попытался отладить классы горячих точек. Что касается этого вопроса здесь, он работает только с обоими процессами, работающими под управлением OpenJDK. Известно ли вам о подобном решении для Oracle JDK? - person Haasip Satang; 09.06.2015
comment
@HaasipSatang Идентификатор объекта в дампе кучи — это адрес объекта на момент дампа (источник). Однако этот идентификатор не является постоянным, поскольку объекты могут перемещаться по куче. - person apangin; 10.06.2015
comment
При использовании Serviceability Agent и клиент, и сервер должны работать с одной и той же версией Java. Oracle JDK основан на OpenJDK, поэтому решение должно быть таким же и для Oracle JDK. - person apangin; 10.06.2015
comment
Дох! Правда, я забыл об этом. Объекты могут перемещаться между разными пространствами памяти :-/ Странно, что у меня никогда не было ни одного работающего случая. Это может означать либо то, что все объекты, которые я тестировал, были перемещены, либо что с моим тестом все еще что-то не так. (Я предполагаю последнее, поскольку, по крайней мере, для классов адрес не должен меняться, верно? Они должны оставаться в постоянном пространстве (в JDK 7)). - person Haasip Satang; 10.06.2015
comment
@HaasipSatang Верно. Как вы получили адрес объекта через Unsafe? Возможно, проблема в этом. - person apangin; 10.06.2015
comment
Я использовал метод, описанный здесь, но ни одно из полученных мной значений не было похоже на то, что было в моем дампе кучи (который я создал программно в том же приложении через MBean). - person Haasip Satang; 10.06.2015
comment
@HaasipSatang А, понятно. На самом деле получить адрес объекта в 64-битной JVM с помощью CompressedOops немного сложнее, чем описано в статье. - person apangin; 10.06.2015
comment
Хорошо, я еще немного поиграю. По крайней мере, я знаю, что тогда общее понимание было правильным. Но, вероятно, сейчас мне все равно нужно думать о совершенно другом подходе (из-за пространств памяти). Идея заключалась в том, чтобы пометить определенные объекты во время выполнения (используя JVMTI), а затем сравнить их с их старым состоянием из дампа кучи. Проблема, очевидно, заключается в идентификации объекта, который у меня есть в памяти, в старом дампе кучи. Любые идеи? Возможно, решением будет добавление примитивного поля в каждый класс с использованием BCI. Проблема в том, что класс Object не может иметь никаких полей. Поэтому я подумал, что пометка может быть лучше. - person Haasip Satang; 11.06.2015
comment
На всякий случай, если кто-то еще ищет это: вы можете проверить класс VMSupport из здесь. Этот класс показывает, как вы можете получить адрес объекта на разных виртуальных машинах (32-битных, 64-битных, сжатых или несжатых). Еще раз спасибо @apangin за все хорошие указатели в правильном направлении! PS: мои объекты действительно просто перемещались между операциями получения адреса объекта и создания дампа. - person Haasip Satang; 13.06.2015
comment
Вы хотите ответить здесь также, поэтому я принимаю ответ, поскольку все рекомендации, которые вы здесь дали, в значительной степени ответили и на этот вопрос? В очередной раз благодарим за помощь. - person Haasip Satang; 13.06.2015