Jak aktywować JMX na mojej JVM, aby uzyskać dostęp za pomocą jconsole?

223

Jak aktywować JMX na JVM, aby uzyskać dostęp za pomocą jconsole?

Mauli
źródło
32
jest to dozwolone i faktycznie jest to dla mnie tylko przypomnienie, ponieważ zawsze zapominam, gdzie skopiować parametry, a teraz wiem, gdzie je znajduję :-)
Mauli
20
Stack Exchange zawsze wyraźnie zachęcał użytkowników do odpowiadania na ich pytania, patrz tutaj: stackoverflow.com/help/self-answer
Tim Büthe
11
Niejednokrotnie szukałem czegoś SO i znalazłem odpowiedź na pytanie ... samodzielnie. I jeden z nich został również przeze mnie zapytany. Dlatego dobrze jest podać własne odpowiedzi. Pomyśl także o wszystkich innych ludziach, którzy mogli napotkać twój problem, jeśli odpowiesz na pytanie, również im pomożesz.
Mike Miller,
2
Zaktualizowany dokument dla Java 8 jest tutaj
Andrew Johnston
@ Mauren: Czy możesz podać odniesienie do swojego zamkniętego pytania, na które sam odpowiedziałeś? Może warto omówić na Meta.
kevinarpe

Odpowiedzi:

290

Odpowiednia dokumentacja znajduje się tutaj:

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

Uruchom program z następującymi parametrami:

-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

Na przykład tak:

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=falsenie jest koniecznie wymagany, ale bez niego nie działa na Ubuntu. Błąd byłby mniej więcej taki:

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)

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

Uważaj również, dzięki-Dcom.sun.management.jmxremote.authenticate=false czemu dostęp jest dostępny dla każdego, ale jeśli używasz go tylko do śledzenia JVM na komputerze lokalnym, nie ma to znaczenia.

Aktualizacja :

W niektórych przypadkach nie mogłem połączyć się z serwerem. Zostało to naprawione, jeśli ustawię również ten parametr:-Djava.rmi.server.hostname=127.0.0.1

Mauli
źródło
9
-Dcom.sun.management.jmxremote.local.only = false jest również potrzebny na
Centos
1
Nit pick: Dziwne jest dla mnie, że com.sun.management.jmxremotema domyślną wartość as true. (Dziękuję Sun!) Aby być bardzo jasnym, szczególnie dla osób mniej zaznajomionych z numerami JMX, używam: com.sun.management.jmxremote=trueRef: docs.oracle.com/javase/8/docs/technotes/guides/management/…
kevinarpe
1
„-Djava.rmi.server.hostname” działało dla mnie jak urok!
Orhun D.
1
ustawienie nazwy hosta na localhost jest bardzo ważne, jeśli próbujesz połączyć się ze zdalnym serwerem przez tunel SSH, co jest bardzo częstym przypadkiem.
Nikhil Owalekar
1
Działa to tylko wtedy, gdy wyłączę zaporę na serwerze. W tym przykładzie otworzyłem port 9010 / tcp, próbowałem też dodać Dcom.sun.management.jmxremote.rmi.port=9011i otworzyć w zaporze ogniowej - nadal nie mogę się połączyć z uruchomioną zaporą ogniową. jakieś pomysły? Czy coś przeoczyłem?
Carmageddon,
70

Praca w kontenerze Docker wprowadziła całą masę dodatkowych problemów z połączeniem, więc mam nadzieję, że to komuś pomoże. W końcu musiałem dodać następujące opcje, które wyjaśnię poniżej:

-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

W przeciwieństwie do używania jconsole lokalnie, musisz zareklamować inny adres IP, niż prawdopodobnie zobaczysz w kontenerze. Musisz zastąpić ${DOCKER_HOST_IP}zewnętrznie rozpoznawalnym adresem IP (nazwa DNS) hosta Docker.

Porty JMX Remote i RMI

Wygląda na to, że JMX wymaga również dostępu do interfejsu zdalnego zarządzania ( jstat ), który używa innego portu do przesyłania niektórych danych podczas arbitrażu połączenia. Nigdzie nie widziałem od razu oczywistego jconsoleustawienia tej wartości. W powiązanym artykule proces był następujący:

  • Spróbuj połączyć się jconsolez włączonym rejestrowaniem
  • Zawieść
  • Dowiedz się, który port jconsolepróbował użyć
  • W razie potrzeby użyj iptables/ firewallrules, aby zezwolić na połączenie tego portu

Chociaż to działa, z pewnością nie jest to rozwiązanie automatyczne. Zdecydowałem się na aktualizację z jconsole do VisualVM, ponieważ pozwala ci to wyraźnie określić port, na którym jstatddziała. W VisualVM dodaj nowy host zdalny i zaktualizuj go o wartości, które korelują z wartościami podanymi powyżej:

Dodaj hosta zdalnego

Następnie kliknij prawym przyciskiem myszy nowe Zdalne połączenie hosta i Add JMX Connection...

Dodaj połączenie JMX

Nie zapomnij zaznaczyć pola wyboru dla Do not require SSL connection. Mam nadzieję, że powinno to umożliwić połączenie.

Joel B.
źródło
-Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.rmi.port=[...]jest również kluczem w przypadku tunelowania JMX / RMI przez SSH. Bez nich zdalne obiekty są dostępne przy użyciu publicznego / głównego / ... adresu IP serwera przy użyciu losowego portu, którego nie można łatwo przekazać dalej.
Thorsten Schöning
1
Mogę potwierdzić, że naprawdę musisz użyć adresu IP zewnętrznego do kontenera. Na przykład nie działa z-Djava.rmi.server.hostname=0.0.0.0
raisercostin
DOCKER_HOST_IPNigdzie nie musiałem używać - po prostu użyłem localhosti przesłałem porty podczas uruchamiania obrazu dokera: -p 9998:9998, -p 9999:9999itp.
Barney
9

Uwaga: Java 6 w najnowszym wcieleniu pozwala jconsole na dołączenie się do uruchomionego procesu nawet po jego uruchomieniu bez inkantacji JMX.

Jeśli jest to dla Ciebie dostępne, rozważ także jvisualvm, ponieważ zapewnia on wiele informacji na temat uruchomionych procesów, w tym profilera.

Thorbjørn Ravn Andersen
źródło
3
Działa to tylko wtedy, gdy używasz jconsole na tym samym hoście, co JVM, który próbujesz monitorować.
Gray
1
@ Thorbjorn Jeśli uruchomię mój program Java bez żadnych parametrów i spróbuję połączyć się z jconsole, widzę w moim programie na liście, ale gdy próbuję się połączyć, to się nie udaje. Myślę, że dzieje się tak z powodu braku certyfikatów SSL. Chciałem tylko zobaczyć wersję demo, dlatego musiałem użyć parametrów określonych w odpowiedzi użytkownika 3013578 i zadziałało to dla mnie (JDK 1.7, Windows 8.1, wersja 64-bitowa).
Kapitan Jack Sparrow,
2
Interfejs API dołączania wymaga, aby jconsole miał taką samą 32/64-bitową maszynę JVM, co uruchomiony program na niektórych platformach.
Thorbjørn Ravn Andersen
1
Czy można wyłączyć to zachowanie?
kevinarpe
7

Używam WAS ND 7.0

Moja JVM potrzebuje wszystkich poniższych argumentów do monitorowania w 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
użytkownik3013578
źródło
Tak, twoja odpowiedź zadziałała dla mnie (JDK 1.7, Windows 8.1 64 bit)
Kapitan Jack Sparrow
6

W systemie Linux użyłem następujących parametrów:

-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

a także edytowałem /etc/hoststak, aby nazwa hosta była tłumaczona na adres hosta (192.168.0.x), a nie na adres zwrotny (127.0.0.1)

alex.pulver
źródło
2

Uruchom aplikację Java z następującymi parametrami wiersza poleceń:

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

Ważne jest, aby użyć parametru -Dcom.sun.management.jmxremote.ssl = false , jeśli nie chcesz konfigurować certyfikatów cyfrowych na hoście jmx.

Jeśli aplikacja została uruchomiona na komputerze o adresie IP 192.168.0.1 , otwórz jconsole , wpisz 192.168.0.1:8855 w polu Zdalny proces i kliknij Połącz .

Wasif
źródło
Jakie jest oczekiwane zachowanie, jeśli zapomnisz -Dcom.sun.management.jmxremote.ssl=false? Czy powinien jconsolewyświetlać się błąd, czy po prostu po prostu nie może się połączyć?
amacleod
2

wraz z poniższymi parametrami wiersza poleceń,

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

Czasami na serwerach Linux nie udaje się połączenie IMX. to jest dlatego, że w chmurze Linux, w / etc / hosts, tak że nazwa hosta jest tłumaczona na adres hosta.

najlepszym sposobem, aby to naprawić, pinguj konkretny serwer linux z innego komputera w sieci i użyj tego adresu IP hosta w

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

Ale nigdy nie polegaj na adresie iPada, który otrzymujesz z serwera Linux przy użyciu ifconfig.me. otrzymany adres IP jest zamaskowany i znajduje się w pliku hosta.

Phani Kumar
źródło
1

Najpierw musisz sprawdzić, czy proces Java jest już uruchomiony z parametrami JMX. Zrób to:

ps -ef | grep java

Sprawdź proces Java, który musisz monitorować. Jeśli widzisz parametr jmx rmi Djmx.rmi.registry.port = xxxx, użyj portu wymienionego tutaj w JavaVideo VVM, aby połączyć go zdalnie pod połączeniem JMX.

Jeśli nie działa przez port rmi jmx, musisz uruchomić proces Java z poniższymi parametrami:

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

Uwaga: numery portów zależą od twojego wyboru.

Teraz możesz użyć tego portu do połączenia jmx. Oto port 1234.

Abhay S.
źródło
Czy po uruchomieniu jmx powinien być w stanie zobaczyć port 1234 używany? sudo lsof -i:1234nic mi nie pokazuje
Gorgon_Union
1

Krok 1: Uruchom aplikację, używając następujących parametrów.

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

Powyższe argumenty wiążą aplikację z portem 9999.

Krok 2: Uruchom jconsole, wykonując polecenie jconsole w wierszu polecenia lub terminalu.

Wybierz „Remote Process:” i wprowadź adres URL jako {IP_Address}: 9999 i kliknij przycisk Connect, aby połączyć się ze zdalną aplikacją.

Możesz skorzystać z tego linku, aby uzyskać kompletną aplikację.

Hari Krishna
źródło