Uruchamianie jmap Nie można otworzyć pliku gniazda

85

Musiałem biec jmap, aby zrobić zrzut stosu mojego procesu. ale jvmwrócił:

Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding

Więc użyłem -F:

./jmap -F -dump:format=b,file=heap.bin 10330
Attaching to process ID 10331, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.51-b03
Dumping heap to heap.bin ...
  1. Używanie -F jest w porządku do robienia zrzutu sterty?
  2. Czekam 20 minut i jeszcze nie skończyłem. Jakieś pomysły, dlaczego?
Rayman
źródło

Odpowiedzi:

181

jmapvs. jmap -F, a także jstackvs. jstack -Fużywają zupełnie innych mechanizmów komunikacji z docelową maszyną JVM.

jmap / jstack

W przypadku uruchamiania bez -Ftych narzędzi użyj mechanizmu dynamicznego dołączania . Działa to w następujący sposób.

  1. Przed połączeniem się z procesem Java 1234 jmaptworzy plik .attach_pid1234w katalogu roboczym procesu docelowego lub w /tmp.

  2. Następnie jmapwysyła SIGQUITdo procesu docelowego. Kiedy JVM przechwyci sygnał i znajdzie .attach_pid1234, rozpoczyna AttachListenerwątek.

  3. AttachListenerWątek tworzy gniazdo domeny UNIX /tmp/.java_pid1234do nasłuchiwania poleceń z narzędzi zewnętrznych.

  4. Ze względów bezpieczeństwa, gdy połączenie (z jmap) jest akceptowane, JVM sprawdza, czy referencje elementu równorzędnego gniazda są równe euidi egidprocesu JVM. Dlatego jmapnie będzie działać, jeśli zostanie uruchomiony przez innego użytkownika (nawet przez roota).

  5. jmapłączy się z gniazdem i wysyła dumpheappolecenie.

  6. To polecenie jest odczytywane i wykonywane przez AttachListenerwątek maszyny JVM. Wszystkie dane wyjściowe są przesyłane z powrotem do gniazda. Ponieważ zrzut sterty jest wykonywany bezpośrednio przez maszynę JVM, operacja jest naprawdę szybka. Jednak JVM może to zrobić tylko w punktach bezpieczeństwa . Jeśli nie można osiągnąć punktu bezpieczeństwa (np. Proces jest zawieszony, nie odpowiada lub trwa długi GC), jmapnastąpi przekroczenie limitu czasu i zakończy się niepowodzeniem.

Podsumujmy zalety i wady Dynamic Attach.

Plusy

  • Zrzut sterty i inne operacje są wykonywane wspólnie przez maszynę JVM z maksymalną prędkością.
  • Możesz użyć dowolnej wersji jmaplub jstackpołączyć się z dowolną inną wersją maszyny JVM.

Cons.

  • Narzędzie powinno być uruchamiane przez tego samego użytkownika ( euid/ egid) co docelowa maszyna JVM.
  • Może być używany tylko na działającej i zdrowej JVM.
  • Nie będzie działać, jeśli docelowa maszyna JVM jest uruchomiona z -XX:+DisableAttachMechanism.

jmap -F / jstack -F

Po uruchomieniu z -Fnarzędziami przełącz się do trybu specjalnego, który obejmuje HotSpot Serviceability Agent . W tym trybie proces docelowy jest zamrażany; narzędzia odczytują pamięć za pomocą narzędzi do debugowania systemu operacyjnego, a mianowicie ptracew systemie Linux.

  1. jmap -Fwywołuje PTRACE_ATTACHdocelową maszynę JVM. Proces docelowy jest bezwarunkowo zawieszany w odpowiedzi na SIGSTOPsygnał.

  2. Narzędzie odczytuje pamięć JVM za pomocą PTRACE_PEEKDATA. ptracemoże czytać tylko jedno słowo na raz, więc do odczytania dużej sterty procesu docelowego potrzeba zbyt wielu wywołań. To jest bardzo i bardzo powolne.

  3. Narzędzie rekonstruuje wewnętrzne struktury JVM w oparciu o znajomość konkretnej wersji JVM. Ponieważ różne wersje maszyny JVM mają inny układ pamięci, -Ftryb działa tylko wtedy, gdy jmappochodzi z tego samego JDK, co docelowy proces Java.

  4. Narzędzie samo tworzy zrzut sterty, a następnie wznawia proces docelowy.

Plusy

  • Nie jest wymagana żadna współpraca z docelową maszyną JVM. Może być używany nawet na zawieszonym procesie.
  • ptracedziała zawsze, gdy wystarczą uprawnienia na poziomie systemu operacyjnego. Np. rootMoże zrzucić procesy wszystkich innych użytkowników.

Cons.

  • Bardzo wolno przy dużych stosach.
  • Narzędzie i proces docelowy powinny pochodzić z tej samej wersji JDK.
  • Punkt bezpieczeństwa nie jest gwarantowany, gdy narzędzie jest podłączane w trybie wymuszonym. Chociaż jmappróbuje obsłużyć wszystkie specjalne przypadki, czasami może się zdarzyć, że docelowa maszyna JVM nie jest w spójnym stanie.

Uwaga

Istnieje szybszy sposób wykonywania zrzutów sterty w trybie wymuszonym. Najpierw utwórz coredump za pomocą gcore, a następnie uruchom jmapwygenerowany plik core. Zobacz powiązane pytanie .

apangin
źródło
84

Właśnie odkryłem, że jmap (i prawdopodobnie jvisualvm, gdy używam go do generowania zrzutu sterty) wymusza, że ​​użytkownik uruchamiający jmap musi być tym samym użytkownikiem, który uruchamia proces, który próbuje zrzucić.

w moim przypadku jvm, dla którego chcę zrzut sterty, jest uruchamiany przez użytkownika systemu Linux „jboss”. więc gdzie sudo jmap -dump:file.bin <pid>zgłaszano „Unable to open socket:”, mogłem pobrać zrzut sterty za pomocą:

sudo -u jboss jmap -dump:file.bin <pid>
ben_wing
źródło
Myślę, że powinno to być \ -dump: file.bin <pid>, ponieważ musisz uciec - podczas przekazywania parametru z sudo do jmap.
adam
To jest to! Musisz także sudo dla jmap i jcmd.
xtian
wow .. To faktycznie zadziałało. To powinna być akceptowana odpowiedź
Lalit Rao
3

Tak jak powiedział ben_wing , możesz biegać z:

sudo -u jboss-as jmap -dump:file.bin <pid>

(w moim przypadku użytkownik jest jboss-as, ale twój może być jbosslub inny.)

Ale to nie wystarczyło, ponieważ poprosił mnie o hasło ( [sudo] password for ec2-user:), chociaż mogłem uruchomić sudobez pytania o hasło przy innych poleceniach.

Znalazłem rozwiązanie tutaj i musiałem tylko dodać sudonajpierw inne :

sudo sudo -u jboss-as jmap -dump:file.bin <pid>

Działa z innymi poleceniami, takimi jak jcmdi jinfoteż.

Lucas Basquerotto
źródło
Podwójnie sudoratuje mój dzień!
Sher10ck
[root@v5 ~]# sudo sudo -u es jmap -dump:file=tmp.bin 26283 zamienia się w błąd sudo: jmap: command not found. Już konfiguruję ścieżkę java w .bash_profile, co mam zrobić.
roamer
@roamer Być może dzieje się tak dlatego, że kiedy uruchamiasz jako esużytkownik, .bash_profilenie jest stosowany (ponieważ zakładam, że profil bash jest powiązany z twoim użytkownikiem). Radzę uwzględnić ścieżkę java w bardziej globalny sposób, a może określić ścieżkę java w poleceniu, na przykład sudo sudo -u es PATH="$PATH:/java/path" jmap -dump:file=tmp.bin 26283(gdzie /java/pathjest ścieżka java i upewnij się, że jest jmapw niej ).
Lucas Basquerotto
Konfiguruję ścieżkę java w /home/es/.bash_profile i mogę używać jmap podczas logowania się z użytkownikiem es. To cmd sudo sudo -u es /usr/java/jdk1.8.0_181-cloudera/bin/jmap -dump:file=tmp.bin 26283działa. Wielkie dzięki.
roamer
2

Jeśli Twoja aplikacja działa jako usługa systemd, powinieneś otworzyć plik usługi, który znajduje się pod /usr/lib/systemd/system/nazwą Twojej usługi i jest tak nazwany. Następnie sprawdź, czy atrybut privateTmp jest prawdziwy.

Jeśli to prawda, należy zmienić ją na fałsz, a następnie odświeżyć usługę za pomocą polecenia w następujący sposób: systemctl daemon-reload systemctl restart [servicename] Jeśli chcesz uruchomić jmap / jcmd przed ponownym uruchomieniem, możesz użyć skryptu execStop w pliku usługi. Po prostu umieść w nim polecenie i wykonajsystemctl stop [service name]

Prosty
źródło
Zanim zaktualizowałem /usr/lib/systemd/system/elasticsearch.service, ustawiając privateTmp na false, otrzymałem ten błąd: Nie można otworzyć pliku gniazda: proces docelowy nie odpowiada lub maszyna wirtualna HotSpot nie została załadowana - mimo że uruchomiłem jmap jako użytkownik elastycznysearch
imdibiji