Mam aplikację Java, którą uruchamiam z konsoli, która z kolei wykonuje inny proces Java. Chcę uzyskać zrzut wątku / sterty tego procesu potomnego.
Na Uniksie mogłem zrobić kill -3 <pid>
AFAIK, ale na Windows AFAIK jedynym sposobem na zrzucenie wątku jest Ctrl-Break w konsoli. Ale to daje mi tylko zrzut procesu rodzica, a nie dziecka.
Czy istnieje inny sposób na zrzucenie stosu?
java
jvm
heap-dump
thread-dump
Kasun Siyambalapitiya
źródło
źródło
Odpowiedzi:
Możesz użyć,
jmap
aby uzyskać zrzut dowolnego uruchomionego procesu, zakładając, że znaszpid
.Użyj Menedżera zadań lub Monitora zasobów, aby uzyskać
pid
. Następnieaby uzyskać stos dla tego procesu.
źródło
Mylisz dwa różne zrzuty Java.
kill -3
generuje zrzut wątku, a nie zrzut stosu.Aby wykonać zrzut wątku w systemie Windows, CTRL+ BREAKjeśli JVM jest procesem pierwszego planu, jest najprostszym sposobem. Jeśli masz uniksopodobną powłokę w systemie Windows, taką jak Cygwin lub MobaXterm, możesz używać jej
kill -3 {pid}
tak, jak w Uniksie.Aby wykonać zrzut wątku w Uniksie, CTRL+ Cjeśli JVM jest procesem na pierwszym planie lub
kill -3 {pid}
będzie działał, dopóki dostaniesz odpowiedni PID dla JVM.Na obu platformach Java jest dostarczana z kilkoma narzędziami, które mogą pomóc. W przypadku zrzutów wątków
jstack {pid}
jest to najlepszy wybór. http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstack.htmlAby zakończyć pytanie o zrzut: zrzuty hałdy nie są powszechnie używane, ponieważ są trudne do interpretacji. Ale zawierają wiele przydatnych informacji, jeśli wiesz, gdzie / jak na nie spojrzeć. Najczęstszym zastosowaniem jest zlokalizowanie wycieków pamięci. Dobrą praktyką jest ustawienie
-D
wiersza polecenia java, aby zrzut sterty był generowany automatycznie po wystąpieniu błędu OutOfMemoryError,-XX:+HeapDumpOnOutOfMemoryError
ale można również ręcznie wywołać zrzut sterty. Najczęstszym sposobem jest użycie narzędzia Javajmap
.UWAGA: to narzędzie nie jest dostępne na wszystkich platformach. Od wersji JDK 1.6
jmap
jest dostępny w systemie Windows.Przykładowy wiersz poleceń wyglądałby podobnie
Wyjściowy plik „myheap.bin” nie jest czytelny dla człowieka (dla większości z nas) i będziesz potrzebować narzędzia do jego analizy. Moje preferencje to MAT. http://www.eclipse.org/mat/
źródło
Myślę, że najlepszym sposobem na utworzenie pliku .hprof w procesie Linux jest komenda jmap . Na przykład:
jmap -dump:format=b,file=filename.hprof {PID}
źródło
Oprócz korzystania ze wspomnianej jconsole / visualvm, możesz używać
jstack -l <vm-id>
w innym oknie wiersza poleceń i przechwytywać dane wyjściowe.<vm-id> można znaleźć za pomocą menedżera zadań (jest to identyfikator procesu w systemach Windows i Unix) lub za pomocą
jps
.Zarówno
jstack
ijps
są uwzględnione w Sun JDK w wersji 6 i wyższych.źródło
Polecam Java VisualVM rozpowszechniany z JDK (jvisualvm.exe). Może łączyć się dynamicznie i uzyskiwać dostęp do wątków i sterty. Znalazłem bezcenne dla niektórych problemów.
źródło
Jeśli korzystasz z serwera w wersji 8 lub nowszej, możesz użyć tego:
źródło
Wypróbuj jedną z poniższych opcji.
W przypadku 32-bitowej maszyny JVM:
W przypadku 64-bitowej maszyny JVM (wyraźnie cytując):
W przypadku 64-bitowej maszyny JVM z algorytmem G1GC w parametrach maszyny wirtualnej (tylko algorytm obiektów aktywnych jest generowany za pomocą algorytmu G1GC):
Powiązane pytanie SE: Błąd zrzutu stosu Java przy użyciu polecenia jmap: Przedwczesny EOF
Zapoznaj się z różnymi opcjami
jmap
tego artykułuźródło
Jeśli chcesz uzyskać zrzut pamięci z braku pamięci, możesz uruchomić Javę z tą opcją
-XX:-HeapDumpOnOutOfMemoryError
patrz strona referencyjna Opcje JVM
źródło
Możesz uruchomić
jconsole
(dołączony do SDK Java 6), a następnie połączyć się z aplikacją Java. Pokaże każdy działający wątek i ślad stosu.źródło
Możesz wysłać
kill -3 <pid>
z Cygwin. Musisz użyćps
opcji Cygwin, aby znaleźć procesy systemu Windows, a następnie po prostu wysłać sygnał do tego procesu.źródło
Musisz przekierować wyjście z drugiego pliku wykonywalnego Java do jakiegoś pliku. Następnie użyj SendSignal, aby wysłać „-3” do drugiego procesu.
źródło
Jeśli używasz JDK 1.6 lub nowszego, możesz użyć
jmap
polecenia, aby wykonać zrzut zrzutu procesu Java, pod warunkiem, że powinieneś znać ProcessID.Jeśli korzystasz z komputera z systemem Windows, możesz użyć Menedżera zadań, aby uzyskać PID. W przypadku komputera z systemem Linux można używać różnych poleceń, takich jak
ps -A | grep java
lubnetstat -tupln | grep java
lubtop | grep java
, w zależności od aplikacji.Następnie możesz użyć polecenia, np.
jmap -dump:format=b,file=sample_heap_dump.hprof 1234
Gdzie 1234 to PID.Dostępne są różne narzędzia do interpretacji pliku hprof. Polecę narzędzie Visualvm Oracle, które jest proste w użyciu.
źródło
Jeśli z jakiegoś powodu nie możesz (lub nie chcesz) korzystać z konsoli / terminala, istnieje alternatywne rozwiązanie. Możesz sprawić, że aplikacja Java wydrukuje dla ciebie zrzut wątku. Kod, który zbiera dane śledzenia stosu, jest dość prosty i można go dołączyć do przycisku lub interfejsu internetowego.
Ta metoda zwróci ciąg, który wygląda następująco:
Dla osób zainteresowanych wersją Java 8 ze strumieniami kod jest jeszcze bardziej kompaktowy:
Możesz łatwo przetestować ten kod za pomocą:
źródło
Poniższy skrypt używa PsExec do łączenia się z inną sesją systemu Windows, dzięki czemu działa nawet w przypadku połączenia za pośrednictwem usługi pulpitu zdalnego.
Napisałem mały skrypt wsadowy dla Java 8 (używając
PsExec
ijcmd
) o nazwiejvmdump.bat
, który zrzuca wątki, stertę, właściwości systemowe i argumenty JVM.Musi być uruchamiany w tej samej sesji Windows użytkownika, który uruchomił JVM, więc jeśli łączysz się przez Pulpit zdalny, może być konieczne uruchomienie wiersza polecenia
Session 0
i uruchomienie go stamtąd. na przykładSpowoduje to wyświetlenie monitu (kliknij ikonę paska zadań u dołu)
View the message
w sesji interaktywnej, która przeniesie Cię do nowej konsoli w drugiej sesji, z której możesz uruchomićjvmdump.bat
skrypt.źródło
Jak uzyskać identyfikator procesu aplikacji Java?
Wykonaj polecenie „jcmd”, aby uzyskać identyfikator procesu aplikacji Java.
Jak uzyskać zrzut wątku?
jcmd PID Thread.print> thread.dump
Link referencyjny
Możesz nawet użyć jstack, aby uzyskać zrzut wątku (jstack PID> thread.dump). Link referencyjny
Jak uzyskać zrzut hałdy?
Użyj narzędzia jmap, aby uzyskać zrzut sterty. jmap -F -dump: live, format = b, file = heap.bin PID
PID oznacza identyfikator procesu aplikacji. Link referencyjny
źródło
Może jcmd ?
Narzędzie Jcmd służy do wysyłania diagnostycznych żądań poleceń do JVM, gdzie są one przydatne do kontrolowania zapisów lotów Java, rozwiązywania problemów i diagnozowania JVM i aplikacji Java.
Narzędzie jcmd zostało wprowadzone w Javie Oracle 7 i jest szczególnie przydatne w rozwiązywaniu problemów z aplikacjami JVM, wykorzystując je do identyfikacji identyfikatorów procesów Java (podobnie jak jps), pozyskiwania zrzutów sterty (podobnie jak jmap), pobierania zrzutów wątków (podobnie jak jstack ), przeglądanie właściwości maszyny wirtualnej, takich jak właściwości systemu i flagi wiersza polecenia (podobnie do jinfo), oraz uzyskiwanie statystyk dotyczących czyszczenia pamięci (podobnie do jstat). Narzędzie jcmd nazwano „szwajcarskim scyzorykiem do badania i rozwiązywania problemów z aplikacją JVM” oraz „ukrytym klejnotem”.
Oto proces, którego musisz użyć, aby wywołać
jcmd
:jcmd <pid> GC.heap_dump <file-path>
Sprawdź to, aby uzyskać więcej informacji na temat zrzutu zrzutu Java .
źródło
Kontynuacja Visualvm:
Jeśli „nie możesz się połączyć” z uruchomioną maszyną JVM z jvisualvm, ponieważ nie uruchomiłeś jej z odpowiednimi argumentami JVM (i jest to na zdalnej skrzynce), uruchom
jstatd
na zdalnej skrzynce, a następnie, zakładając, że masz bezpośrednie połączenie, dodaj jako „zdalny host” w visualvm, kliknij dwukrotnie nazwę hosta, a wszystkie inne maszyny JVM w tym polu magicznie pojawią się w visualvm.Jeśli nie masz „bezpośredniego połączenia” z portami na tym urządzeniu, możesz to zrobić również przez serwer proxy .
Gdy zobaczysz pożądany proces, przejdź do niego w jvisualvm i użyj zakładki monitor -> przycisk „heapdump”.
źródło
Poniższy kod Java jest używany do uzyskania zrzutu stosu procesu Java, podając PID. Program używa zdalnego połączenia JMX do zrzucenia sterty. Może to być pomocne dla kogoś.
}
źródło
Aby wykonać zrzut wątku / zrzut stosu z procesu potomnego Java w systemie Windows, musisz zidentyfikować identyfikator procesu potomnego jako pierwszy krok.
Wydając polecenie: jps , będziesz w stanie uzyskać wszystkie identyfikatory procesów Java, które są uruchomione na komputerze z systemem Windows. Z tej listy musisz wybrać identyfikator procesu potomnego. Po utworzeniu identyfikatora procesu potomnego dostępne są różne opcje przechwytywania zrzutu wątku i zrzutu stosu.
Przechwytywanie zrzutów wątków:
Istnieje 8 opcji przechwytywania zrzutów wątków:
Szczegółowe informacje na temat każdej opcji można znaleźć w tym artykule . Po przechwyceniu zrzutów wątków możesz używać narzędzi takich jak fastThread , Samuraito analizować zrzuty wątków.
Przechwytywanie zrzutów sterty:
Istnieje 7 opcji przechwytywania zrzutów sterty:
jmap
-XX: + HeapDumpOnOutOfMemoryError
jcmd
JVisualVM
JMX
Podejście programowe
Konsole administracyjne
Szczegółowe informacje na temat każdej opcji można znaleźć w tym artykule . Po przechwyceniu zrzutu sterty możesz użyć narzędzi takich jak narzędzie Eclipse Memory Analysis , HeapHero do analizy przechwyconych zrzutów sterty.
źródło
W Oracle JDK mamy polecenie o nazwie jmap (dostępne w folderze bin Java Home). użycie polecenia jest następujące
Przykład: jmap -dump: live, format = b, file = heap.bin (pid)
źródło