Am o aplicație Java care am rulat de pe o consola care, la rândul său execută un alt Java proces. Vreau pentru a obține un fir/morman de faptul că procesul de copil.
Pe Unix, am putea face un omor -3
Există un alt mod de a obține acel morman de gunoi?
Puteți folosi jmappentru a obține o groapa de orice proces care rulează, că știi ce ai de
pid`.
Utilizarea Task Manager sau Resource Monitor pentru a obține pid
. Apoi
jmap -dump:format=b,file=cheap.hprof <pid>
pentru a obține heap pentru acest proces.
Faci o confuzie între două tipuri diferite de java gropile. ucide -3
generează un fir de gunoi, nu un morman de gunoi.
Thread dump = stivă pentru fiecare fir în JVM ieșire la stdout ca text.
Morman = conținutul memoriei pentru JVM procesul de ieșire într-un fișier binar.
Pentru a lua un fir de basculante pe Windows, CTRL+PAUZĂ în cazul în care JVM este în prim-plan procesul este cel mai simplu mod. Dacă aveți un unix-cum ar fi shell pe Windows ca Cygwin sau MobaXterm, puteți utiliza omor -3 {pid}` ca tine poate în Unix.
Pentru a lua un fir de gunoi în Unix, CTRL+C în cazul în care JVM este în prim-plan procesul sau ucide -3 {pid}` va funcționa atâta timp cât aveți dreptul de PID pentru JVM.
Fie cu platforma, Java vine cu mai multe utilitare care vă pot ajuta. Pentru firul gropile, jstack {pid}
este cel mai bun pariu. http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstack.html
Doar pentru a termina groapa de gunoi întrebare: Heap gropile nu sunt frecvent utilizate, deoarece acestea sunt dificil de interpretat. Dar, ei au o mulțime de informații utile în ele, dacă știi unde/cum să se uite la ei. Cea mai comună utilizare este de a localiza scurgeri de memorie. Este o bună practică pentru a seta -D
pe java linie de comandă, astfel încât morman de gunoi este generat automat la o OutOfMemoryError, -XX:+HeapDumpOnOutOfMemoryError
Dar, puteți declanșa manual un morman de gunoi, de asemenea. Cel mai comun mod este de a utiliza java utilitate jmap
.
NOTĂ: acest utilitar nu este disponibil pe toate platformele. Ca de JDK 1.6, jmap
este disponibil pe Windows.
Un exemplu de linie de comandă ar arata ceva de genul
jmap -dump:file=myheap.bin {pid of the JVM}
Ieșire "myheap.bin" nu este lizibil (pentru majoritatea dintre noi), și veți avea nevoie de un instrument pentru a-l analiza. Preferința mea este MAT. http://www.eclipse.org/mat/
În plus față de utilizarea menționat jconsole/visualvm, puteți utiliza `jstack -l
&Amp;lt;ban-id-ul> pot fi găsite cu ajutorul task manager (este id-ul procesului pe windows și unix), sau folosind jps
.
Ambele `jstack " și " jps se includ în Soare versiunea JDK 6 și mai mare.
Încercați una dintre opțiunile de mai jos.
jmap -basculante:format=b,file=
jmap -J-d64 -basculante:format=b,file=
jmap -J-d64 -basculante:live,format=b,file=
Legat SE pune problema: https://stackoverflow.com/questions/36604102/java-heap-dump-error-with-jmap-command-premature-eof/
Avea o privire la diferitele opțiuni de jmap` la articolul
Dacă sunteți pe server-jre 8 și mai sus, puteți utiliza acest lucru:
jcmd PID GC.heap_dump /tmp/dump
Dacă doriți un heapdump pe afară-de-memorie, puteți începe Java cu opțiunea -XX:-HeapDumpOnOutOfMemoryError
Aveți pentru a redirecționa producția de doua java executabil pentru un fișier. Apoi, utilizați SendSignal la trimite "-3" pentru al doilea proces.
Dacă utilizați JDK 1.6 sau mai sus, puteți folosi jmap comandă pentru a lua un morman de un Java proces, starea este cunoscut ProcessID.
Dacă sunteți pe Windows, aveți posibilitatea să utilizați Managerul de activități pentru a obține PID. Pentru Linux, puteți utiliza soiuri de comandă ca ps-A | grep java " sau "netstat -tupln | grep java" sau " sus | grep java
, depinde de cererea dumneavoastră.
Apoi, puteți utiliza comanda ca jmap -basculante:format=b,file=sample_heap_dump.hprof 1234
unde 1234 este PID.
Există soiuri de instrument disponibil pentru a interpreta hprof fișier. Eu va recomand Oracle's visualvm instrument, care este simplu de utilizat.
Am scris un mic script batch pentru Java 8 (folosind PsExec
și jcmd
) numit jvmdump.bat
, care a haldelor de fire, heap, proprietăți sistem, și JVM args.
:: set the paths for your environment
set PsExec=C:\Apps\SysInternals\PsExec.exe
set JAVA_HOME=C:\Apps\Java\jdk1.8.0_121
set DUMP_DIR=C:\temp
@echo off
set PID=%1
if "%PID%"=="" (
echo usage: jvmdump.bat {pid}
exit /b
)
for /f "tokens=2,3,4 delims=/ " %%f in ('date /t') do set timestamp_d=%%h%%g%%f
for /f "tokens=1,2 delims=: " %%f in ('time /t') do set timestamp_t=%%f%%g
set timestamp=%timestamp_d%%timestamp_t%
echo datetime is: %timestamp%
echo ### Version >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.version >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Uptime >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.uptime >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Command >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.command_line >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Flags >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.flags >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Properties >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.system_properties >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% Thread.print -l >"%DUMP_DIR%\%PID%-%timestamp%-threads.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% GC.heap_dump "%DUMP_DIR%\%PID%-%timestamp%-heap.hprof"
echo Dumped to %DUMP_DIR%
Trebuie să fi rulat în același Windows sesiune de utilizatorul care a început JVM, deci, dacă vă conecta prin Remote Desktop s-ar putea nevoie pentru a lansa o linie de comandă în Sesiune 0` și rulați-l de acolo. de exemplu
%PsExec% -s -h -d -i 0 cmd.exe
Acest lucru va solicita (faceți clic pe pictograma din bara de activități în partea de jos) pentru a Vedea mesajul în sesiune interactivă, care vă va duce la noua consola în alte sesiuni la care puteți rula
jvmdump.bat` script-ul.
Dacă poți't (sau don't vrei) pentru a utiliza consola/terminal pentru un motiv oarecare, nu există o soluție alternativă. Puteți face aplicația Java print firul basculante pentru tine. Codul care colectează Stivei este rezonabil de simplu și poate fi atașat la un buton sau o interfață web.
private static String getThreadDump() {
Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
StringBuilder out = new StringBuilder();
for (Map.Entry<Thread, StackTraceElement[]> entry : allStackTraces.entrySet()) {
Thread thread = entry.getKey();
StackTraceElement[] elements = entry.getValue();
out.append(String.format("%s | prio=%d | %s", thread.getName(), thread.getPriority(), thread.getState()));
out.append('\n');
for (StackTraceElement element : elements) {
out.append(element.toString()).append('\n');
}
out.append('\n');
}
return out.toString();
}
Aceasta metoda va returna un șir de caractere care arata ca aceasta:
main | prio=5 | RUNNABLE
java.lang.Thread.dumpThreads(Native Method)
java.lang.Thread.getAllStackTraces(Thread.java:1607)
Main.getThreadDump(Main.java:8)
Main.main(Main.java:36)
Monitor Ctrl-Break | prio=5 | RUNNABLE
java.net.PlainSocketImpl.initProto(Native Method)
java.net.PlainSocketImpl.<clinit>(PlainSocketImpl.java:45)
java.net.Socket.setImpl(Socket.java:503)
java.net.Socket.<init>(Socket.java:424)
java.net.Socket.<init>(Socket.java:211)
com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:59)
Finalizer | prio=8 | WAITING
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
Reference Handler | prio=10 | WAITING
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:502)
java.lang.ref.Reference.tryHandlePending(Reference.java:191)
java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
Pentru cei interesați într-un Java versiunea 8 cu fluxuri, codul este chiar mai compact:
private static String getThreadDump() {
Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
StringBuilder out = new StringBuilder();
allStackTraces.forEach((thread, elements) -> {
out.append(String.format("%s | prio=%d | %s", thread.getName(), thread.getPriority(), thread.getState()));
out.append('\n');
Arrays.stream(elements).forEach(element -> out.append(element.toString()).append('\n'));
out.append('\n');
});
return out.toString();
}
Puteți testa cu ușurință acest cod cu:
System.out.print(getThreadDump());
Visualvm de urmarire:
Dacă aveți "poate't connect" la funcționare JVM din jvisualvm pentru că nu - 't-l înceapă cu dreptul de argumente JVM (și's de la distanță cutie), run jstatd
de pe telecomanda cutie, apoi, presupunând că aveți o conexiune directă, adăugați-l ca un "gazdă de la distanță" în visualvm, faceți dublu clic pe numele de gazdă, și toate celelalte JVM's pe cutie magic va apărea în visualvm.
Dacă tu nu't au "conexiune directă" pentru porturile de pe cutie, de asemenea, puteți face acest lucru printr-un proxy.
Odată ce se poate vedea procesul doriți, găuriți în ea în jvisualvm și de a folosi fila monitor -> "heapdump" buton.
Mai jos codul java este folosit pentru a obține Morman de un Java Proces prin furnizarea de PID. Programul foloseste la Distanță JMX conexiune la groapa de heap. Acesta poate fi de ajutor pentru cineva.
import java.lang.management.ManagementFactory;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.lang.reflect.Method;
public class HeapDumper {
public static final String HOST = "192.168.11.177";
public static final String PORT = "1600";
public static final String FILE_NAME = "heapDump.hprof";
public static final String FOLDER_PATH = "C:/";
private static final String HOTSPOT_BEAN_NAME ="com.sun.management:type=HotSpotDiagnostic";
public static void main(String[] args) {
if(args.length == 0) {
System.out.println("Enter PID of the Java Process !!!");
return;
}
String pidString = args[0];
int pid = -1;
if(pidString!=null && pidString.length() > 0) {
try {
pid = Integer.parseInt(pidString);
}
catch(Exception e) {
System.out.println("PID is not Valid !!!");
return;
}
}
boolean isHeapDumpSuccess = false;
boolean live = true;
if(pid > 0) {
MBeanServerConnection beanServerConn = getJMXConnection();
if(beanServerConn!=null) {
Class clazz = null;
String dumpFile = FOLDER_PATH+"/"+FILE_NAME;
try{
clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean");
Object hotspotMBean = ManagementFactory.newPlatformMXBeanProxy(beanServerConn, HOTSPOT_BEAN_NAME, clazz);
Method method = clazz.getMethod("dumpHeap", new Class[]{String.class , boolean.class});
method.setAccessible(true);
method.invoke(hotspotMBean , new Object[] {dumpFile, new Boolean(live)});
isHeapDumpSuccess = true;
}
catch(Exception e){
e.printStackTrace();
isHeapDumpSuccess = false;
}
finally{
clazz = null;
}
}
}
if(isHeapDumpSuccess){
System.out.println("HeapDump is Success !!!");
}
else{
System.out.println("HeapDump is not Success !!!");
}
}
private static MBeanServerConnection getJMXConnection() {
MBeanServerConnection mbeanServerConnection = null;
String urlString = "service:jmx:rmi:///jndi/rmi://" + HOST + ":" + PORT + "/jmxrmi";
try {
JMXServiceURL url = new JMXServiceURL(urlString);
JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
mbeanServerConnection = jmxConnector.getMBeanServerConnection();
System.out.println("JMX Connection is Success for the URL :"+urlString);
}
catch(Exception e) {
System.out.println("JMX Connection Failed !!!");
}
return mbeanServerConnection;
}
}
Poate jcmd?
Jcmd utilitar este folosit pentru a trimite comanda diagnostic cereri pentru JVM, în cazul în care aceste cereri sunt utile pentru controlul Java Zbor Înregistrări, depanarea și diagnosticarea JVM și Aplicații Java.
La jcmd instrument a fost introdus cu Oracle's Java 7 și este deosebit de util în depanare probleme cu JVM aplicații folosindu-l pentru a identifica Java procesele de' Id-uri (înrudită cu jps), dobândirea de gropile de heap (înrudită cu jmap), dobândirea fir halde (înrudită cu jstack), vizualizarea virtual machine caracteristici, cum ar fi proprietățile de sistem și de linie de comandă steaguri (înrudită cu jinfo), și dobândirea de colectare a gunoiului de statistică (înrudită cu jstat). La jcmd instrument a fost numit "un swiss army knife pentru investigarea și rezolvarea problemelor cu JVM aplicație" și "bijuterie ascunse."
Aici este procesul de care aveți nevoie pentru a utiliza în invocarea jcmd
:
jcmd <pid> GC.heap_dump <file-path>
Check it out pentru mai multe informații despre a lua Java morman.
Pe un Oracle JDK, avem o comanda numita jmap (disponibil în folderul bin de Java Acasă). utilizarea de comanda vine, după cum urmează
jmap (opțiune) (pid)
Exemplu: jmap -basculante:live,format=b,file=heap.bin (pid)