Как активировать JMX на моей JVM для доступа через jconsole?


223

Как активировать JMX на JVM для доступа через jconsole?


32
это разрешено, и на самом деле это всего лишь напоминание для меня, потому что я всегда забываю, откуда копировать параметры, и теперь я знаю, где я его нахожу :-)
Mauli

20
Stack Exchange всегда явно побуждал пользователей отвечать на свои вопросы, см. Здесь: stackoverflow.com/help/self-answer
Тим Бюте,

11
Я не раз искал что-то ТАК и находил ответ на вопрос ... сам. И один из них был задан и мной. Вот почему это хорошо, чтобы добавить свои собственные ответы. Кроме того, подумайте обо всех других людях, которые могли столкнуться с вашей проблемой, если вы ответите на свой вопрос, вы тоже им поможете.
Майк Миллер

2
Обновленный документ для Java 8 уже здесь
Эндрю Джонстон,

@Mauren: Можете ли вы дать ссылку на закрытый вопрос, на который вы сами ответили? Возможно, стоит обсудить на Meta.
Кевинарпе

Ответы:


290

Соответствующую документацию можно найти здесь:

http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html

Запустите вашу программу со следующими параметрами:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.rmi.port=9010
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

Например, вот так:

java -Dcom.sun.management.jmxremote \
  -Dcom.sun.management.jmxremote.port=9010 \
  -Dcom.sun.management.jmxremote.local.only=false \
  -Dcom.sun.management.jmxremote.authenticate=false \
  -Dcom.sun.management.jmxremote.ssl=false \
  -jar Notepad.jar

-Dcom.sun.management.jmxremote.local.only=falseне обязательно требуется, но без него он не работает в Ubuntu. Ошибка будет примерно такой:

01 Oct 2008 2:16:22 PM sun.rmi.transport. customer .TCPTransport$AcceptLoop executeAcceptLoop
WARNING: RMI TCP Accept-0: accept loop for ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=37278] throws
java.io.IOException: The server sockets created using the LocalRMIServerSocketFactory only accept connections from clients running on the host where the RMI remote objects have been exported.
    at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:89)
    at sun.rmi.transport. customer .TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:387)
    at sun.rmi.transport. customer .TCPTransport$AcceptLoop.run(TCPTransport.java:359)
    at java.lang.Thread.run(Thread.java:636)

см. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6754672

Также будьте осторожны с тем,-Dcom.sun.management.jmxremote.authenticate=false что делает доступ доступным для всех, но если вы используете его только для отслеживания JVM на локальном компьютере, это не имеет значения.

Обновление :

В некоторых случаях я не смог добраться до сервера. Затем это было исправлено, если я также установил этот параметр:-Djava.rmi.server.hostname=127.0.0.1


9
-Dcom.sun.management.jmxremote.local.only = false также необходим для Centos сейчас
LenW

1
Nit pick: мне странно, что com.sun.management.jmxremoteзначение по умолчанию равно true. (Спасибо, Солнце!) Чтобы быть предельно ясным, особенно для тех, кто менее знаком с JMX-пользователями, я использую: com.sun.management.jmxremote=trueRef: docs.oracle.com/javase/8/docs/technotes/guides/management/…
kevinarpe

1
"-Djava.rmi.server.hostname" работал для меня как шарм!
Орхун Д.

1
установка имени хоста на localhost очень важна, если вы пытаетесь подключиться к удаленному серверу через туннель SSH, что является очень распространенным случаем.
Нихил Овалекар

1
Это работает, только если я отключаю брандмауэр на сервере. Я открыл порт 9010 / tcp в этом примере, конечно, я также попытался добавить Dcom.sun.management.jmxremote.rmi.port=9011и открыть в брандмауэре - все еще не могу соединиться с брандмауэром. Есть предположения? Я что-то пропустил?
Carmageddon

70

Запуск в контейнере Docker привел к множеству дополнительных проблем при подключении, так что, надеюсь, это кому-нибудь поможет. В итоге мне нужно было добавить следующие параметры, которые я объясню ниже:

-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=${DOCKER_HOST_IP}
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.rmi.port=9998

DOCKER_HOST_IP

В отличие от локального использования jconsole, вы должны объявить другой IP-адрес, который вы, вероятно, не увидите в контейнере. Вам нужно будет заменить ${DOCKER_HOST_IP}на внешне разрешаемый IP (DNS-имя) вашего хоста Docker.

Порты JMX Remote и RMI

Похоже, JMX также требуется доступ к интерфейсу удаленного управления ( jstat ), который использует другой порт для передачи некоторых данных при арбитраже соединения. Я не видел нигде сразу очевидного, jconsoleчтобы установить это значение. В связанной статье процесс был:

  • Попробуйте подключиться jconsoleс включенным ведением журнала
  • Потерпеть поражение
  • Выяснить, какой порт jconsoleпытался использовать
  • При необходимости используйте iptables/ firewallrules, чтобы разрешить подключение к этому порту.

Хотя это работает, это, конечно, не автоматизируемое решение. Я выбрал обновление с jconsole до VisualVM, поскольку оно позволяет явно указывать порт, на котором jstatdвыполняется. В VisualVM добавьте новый удаленный хост и обновите его значениями, соответствующими указанным выше:

Добавить удаленный хост

Затем щелкните правой кнопкой мыши новое подключение к удаленному хосту и Add JMX Connection...

Добавить соединение JMX

Не забудьте установить флажок для Do not require SSL connection. Надеюсь, это позволит вам подключиться.


-Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.rmi.port=[...]также является ключом в случае туннелирования JMX / RMI через SSH. Без них доступ к удаленным объектам осуществляется с использованием общедоступного / основного / ... IP-адреса сервера с использованием некоторого случайного порта, который не может быть легко переадресован.
Торстен Шёнинг,

1
Я могу подтвердить, что вам действительно нужно использовать внешний IP-адрес контейнера. Например, это не работает с-Djava.rmi.server.hostname=0.0.0.0
raisercostin

Мне не нужно было DOCKER_HOST_IPнигде использовать - я просто использовал localhostи перенаправлял порты при запуске образа докера: -p 9998:9998, -p 9999:9999и т. Д.
Барни

9

Обратите внимание, что Java 6 в последней версии позволяет jconsole присоединяться к работающему процессу даже после его запуска без использования JMX.

Если это доступно вам, также рассмотрите jvisualvm, поскольку он предоставляет обширную информацию о запущенных процессах, включая профилировщик.


3
Это работает только в том случае, если вы используете jconsole на том же хосте, что и JVM, которую вы пытаетесь отслеживать.
Серый

1
@ Thorbjorn Если я запускаю свою Java-программу без каких-либо параметров и пытаюсь подключиться с помощью jconsole, я вижу в своей программе список, но при попытке подключиться она не работает. Я думаю, что это из-за отсутствия сертификатов SSL. Я просто хотел посмотреть демо, поэтому мне пришлось использовать параметры, указанные в ответе user3013578, и это сработало для меня (JDK 1.7, Windows 8.1, 64 бит).
Капитан Джек Воробей

2
Для API подключения требуется, чтобы jconsole имела ту же 32/64 битную JVM, что и запущенная программа на некоторых платформах.
Торбьерн Равн Андерсен

1
Можно ли отключить это поведение?
Кевинарпе

7

Я использую WAS ND 7.0

Моей JVM нужно отслеживать все следующие аргументы в JConsole

    -Djavax.management.builder.initial= 
    -Dcom.sun.management.jmxremote 
    -Dcom.sun.management.jmxremote.port=8855 
    -Dcom.sun.management.jmxremote.authenticate=false 
    -Dcom.sun.management.jmxremote.ssl=false

Да, мой ответ сработал для меня (JDK 1.7, windows 8.1 64 bit)
Капитан Джек Воробей

6

В Linux я использовал следующие параметры:

-Djavax.management.builder.initial= 
-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=9010 
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false

а также я отредактировал /etc/hostsтак, чтобы имя хоста разрешалось в адрес хоста (192.168.0.x), а не адрес обратной петли (127.0.0.1)


2

Запустите ваше Java-приложение со следующими параметрами командной строки:

-Dcom.sun.management.jmxremote.port=8855
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

Важно использовать параметр -Dcom.sun.management.jmxremote.ssl = false, если вы не хотите устанавливать цифровые сертификаты на хосте jmx.

Если вы запустили свое приложение на компьютере с IP-адресом 192.168.0.1 , откройте jconsole , поместите 192.168.0.1:8855 в поле Удаленный процесс и нажмите Подключиться .


Какое поведение ожидается, если вы забудете -Dcom.sun.management.jmxremote.ssl=false? Должно jconsoleотображаться сообщение об ошибке, или он просто не сможет подключиться?
Amacleod

2

наряду с нижеприведенными параметрами командной строки,

-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

Иногда на серверах Linux соединение IMX не удается. это связано с тем, что в облачном хосте linux, в / etc / hosts, чтобы имя хоста соответствовало адресу хоста.

лучший способ исправить это - пропинговать конкретный сервер Linux с другой машины в сети и использовать этот IP-адрес хоста в

-Djava.rmi.server.hostname=IP address that obtained when you ping that linux server.

Но никогда не полагайтесь на IP-адрес, полученный с сервера Linux с помощью ifconfig.me. ip, который вы получаете там, является замаскированным, который присутствует в файле хоста.


1

Сначала вам нужно проверить, работает ли ваш Java-процесс с параметрами JMX. Сделай это:

ps -ef | grep java

Проверьте ваш Java-процесс, который нужно отслеживать. Если вы видите параметр jmx rmi Djmx.rmi.registry.port = xxxx, то используйте порт, упомянутый здесь, в вашем java visualvm, чтобы удаленно подключить его через соединение jmx.

Если он не работает через порт jmx rmi, вам нужно запустить процесс java с указанными ниже параметрами:

-Djmx.rmi.registry.port=1234 -Djmx.rmi.port=1235 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false

Примечание: номера портов основаны на вашем выборе.

Теперь вы можете использовать этот порт для соединения jmx. Вот это порт 1234.


Должны ли вы видеть порт 1234, используемый jmx, после запуска этого? sudo lsof -i:1234ничего не показывает для меня
Gorgon_Union

1

Шаг 1: Запустите приложение, используя следующие параметры.

-Dcom.sun.management.jmxremote.port=9999 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false

Приведенные выше аргументы привязывают приложение к порту 9999.

Шаг 2: Запустите jconsole, выполнив команду jconsole в командной строке или терминале.

Выберите «Удаленный процесс:» и введите URL-адрес как {IP_Address}: 9999 и нажмите кнопку «Подключиться» для подключения к удаленному приложению.

Вы можете обратиться по этой ссылке для полного применения.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.