jmap
vs. jmap -F
, a także jstack
vs. jstack -F
używają zupełnie innych mechanizmów komunikacji z docelową maszyną JVM.
jmap / jstack
W przypadku uruchamiania bez -F
tych narzędzi użyj mechanizmu dynamicznego dołączania . Działa to w następujący sposób.
Przed połączeniem się z procesem Java 1234 jmap
tworzy plik .attach_pid1234
w katalogu roboczym procesu docelowego lub w /tmp
.
Następnie jmap
wysyła SIGQUIT
do procesu docelowego. Kiedy JVM przechwyci sygnał i znajdzie .attach_pid1234
, rozpoczyna AttachListener
wątek.
AttachListener
Wątek tworzy gniazdo domeny UNIX /tmp/.java_pid1234
do nasłuchiwania poleceń z narzędzi zewnętrznych.
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 euid
i egid
procesu JVM. Dlatego jmap
nie będzie działać, jeśli zostanie uruchomiony przez innego użytkownika (nawet przez roota).
jmap
łączy się z gniazdem i wysyła dumpheap
polecenie.
To polecenie jest odczytywane i wykonywane przez AttachListener
wą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), jmap
nastą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
jmap
lub jstack
połą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 -F
narzę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 ptrace
w systemie Linux.
jmap -F
wywołuje PTRACE_ATTACH
docelową maszynę JVM. Proces docelowy jest bezwarunkowo zawieszany w odpowiedzi na SIGSTOP
sygnał.
Narzędzie odczytuje pamięć JVM za pomocą PTRACE_PEEKDATA
. ptrace
moż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.
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, -F
tryb działa tylko wtedy, gdy jmap
pochodzi z tego samego JDK, co docelowy proces Java.
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.
ptrace
działa zawsze, gdy wystarczą uprawnienia na poziomie systemu operacyjnego. Np. root
Moż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ż
jmap
pró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 jmap
wygenerowany plik core. Zobacz powiązane pytanie .
Tak jak powiedział ben_wing , możesz biegać z:
(w moim przypadku użytkownik jest
jboss-as
, ale twój może byćjboss
lub inny.)Ale to nie wystarczyło, ponieważ poprosił mnie o hasło (
[sudo] password for ec2-user:
), chociaż mogłem uruchomićsudo
bez pytania o hasło przy innych poleceniach.Znalazłem rozwiązanie tutaj i musiałem tylko dodać
sudo
najpierw inne :Działa z innymi poleceniami, takimi jak
jcmd
ijinfo
też.źródło
sudo
ratuje mój dzień![root@v5 ~]# sudo sudo -u es jmap -dump:file=tmp.bin 26283
zamienia się w błądsudo: jmap: command not found
. Już konfiguruję ścieżkę java w .bash_profile, co mam zrobić.es
użytkownik,.bash_profile
nie 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ładsudo sudo -u es PATH="$PATH:/java/path" jmap -dump:file=tmp.bin 26283
(gdzie/java/path
jest ścieżka java i upewnij się, że jestjmap
w niej ).sudo sudo -u es /usr/java/jdk1.8.0_181-cloudera/bin/jmap -dump:file=tmp.bin 26283
działa. Wielkie dzięki.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]
źródło