jvm
1. jps
用来查看JVM信息,所有具有访问权限的java进程的具体状态。包括PID, 进程启动路径以及启动参数等。 可以理解为linux上的PS 子集。
命令格式: jps [-q] [-mlvV] [<hostid>]
-q 只输出pid
-m 输出传递给main方法的参数
-l 输出应用程序住类的完整包名,或者是应用程序jar文件的完整路径
-v 输出传给JVM的参数
```
sudo -u admin jps
28580 Jps
6272 Bootstrap
sudo -u admin jps -q
26626
6272
sudo -u admin jps -l
6272 org.apache.catalina.startup.Bootstrap
28298 sun.tools.jps.Jps
sudo -u admin jps -m
6272 Bootstrap start
27633 Jps -m
sudo -u admin jps localhost:7001
28070 Jps
6272 Bootstrap
```
2. jmap
简介: 打印java进程中的所有对象情况,例如产生哪些对象,以及对象数量
命令格式: jmap [option] <pid>
2.1 sudo -u admin jmap -dump:live,format=b,file=heap 5929 使用二进制形式,将JVMheap内容输出到outputFile, live 为可选项,表示只输出活的对象到文件。
2.2 jmap -finalizerinfo <PID> 打印正在等候回收的对象信息
sudo -u admin jmap -finalizerinfo 5929
Attaching to process ID 5929, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.65-b04-internal
Number of objects pending for finalization: 0
2.3 jmap -heap <PID> 打印heap的概要信息,GC使用算法等信息;
sudo -u admin jmap -heap 5929
Attaching to process ID 5929, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.65-b04-internal
using parallel threads in the new generation.
using thread-local object allocation.
Concurrent Mark-Sweep GC
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1342177280 (1280.0MB)
NewSize = 335544320 (320.0MB)
MaxNewSize = 335544320 (320.0MB)
OldSize = 5439488 (5.1875MB)
NewRatio = 2
SurvivorRatio = 10
PermSize = 100663296 (96.0MB)
MaxPermSize = 629145600 (600.0MB)
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
New Generation (Eden + 1 Survivor Space):
capacity = 307625984 (293.375MB)
used = 64660584 (61.665138244628906MB)
free = 242965400 (231.7098617553711MB)
21.019220535024765% used
Eden Space:
capacity = 279707648 (266.75MB)
used = 57251752 (54.599525451660156MB)
free = 222455896 (212.15047454833984MB)
20.468425661353386% used
From Space:
capacity = 27918336 (26.625MB)
used = 7408832 (7.06561279296875MB)
free = 20509504 (19.55938720703125MB)
26.537512837441316% used
To Space:
capacity = 27918336 (26.625MB)
used = 0 (0.0MB)
free = 27918336 (26.625MB)
0.0% used
concurrent mark-sweep generation:
capacity = 1006632960 (960.0MB)
used = 126755184 (120.88316345214844MB)
free = 879877776 (839.1168365478516MB)
12.591996192932129% used
Perm Generation:
capacity = 161787904 (154.29296875MB)
used = 114364384 (109.06637573242188MB)
free = 47423520 (45.226593017578125MB)
70.68784573660092% used
42485 interned Strings occupying 4413184 bytes.
2.4 jmap -histo[:live] 打印每个类的实例数目,内存占用情况,类全名。
sudo -u admin jmap -histo:live 5929
num #instances #bytes class name
----------------------------------------------
1: 200445 29877368 <constMethodKlass>
2: 200445 27273048 <methodKlass>
3: 17102 20779408 <constantPoolKlass>
4: 184717 20052536 [B
5: 187747 19194584 [C
6: 17097 12442624 <instanceKlassKlass>
7: 13082 11212768 <constantPoolCacheKlass>
8: 19783 7304520 [I
9: 184531 4428744 java.lang.String
10: 48520 3881600 java.lang.reflect.Method
11: 5919 3642984 <methodDataKlass>
12: 60424 3383744 org.codehaus.groovy.runtime.metaclass.MetaMethodIndex$Entry
13: 98877 3164064 java.util.HashMap$Entry
14: 92759 2968288 java.util.concurrent.ConcurrentHashMap$HashEntry
15: 81643 2959208 [Ljava.lang.Object;
2.5 jmap -permstat <PID> 打印classload 和 jvm heap持久层的信息.
sudo -u admin jmap -permstat 5929
Attaching to process ID 5929, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.65-b04-internal
finding class loader instances ..
done.
computing per loader stat ..done.
please wait.. computing liveness................ReversePtrs: WARNING: sun.jvm.hotspot.debugger.UnmappedAddressException: dfd12e70 during traversal
liveness analysis may be inaccurate ...
class_loaderclassesbytesparent_loaderalive?type
<bootstrap>280016525816 null live<internal>
0x00000000a13e2aa000Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at sun.tools.jmap.JMap.runTool(JMap.java:197)
at sun.tools.jmap.JMap.main(JMap.java:128)
Caused by: sun.jvm.hotspot.debugger.UnmappedAddressException: df564748
at sun.jvm.hotspot.debugger.PageCache.checkPage(PageCache.java:208)
at sun.jvm.hotspot.debugger.PageCache.getData(PageCache.java:63)
at sun.jvm.hotspot.debugger.DebuggerBase.readBytes(DebuggerBase.java:217)
at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.readCInteger(LinuxDebuggerLocal.java:482)
at sun.jvm.hotspot.debugger.DebuggerBase.readCompOopAddressValue(DebuggerBase.java:459)
at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal.readCompOopHandle(LinuxDebuggerLocal.java:442)
at sun.jvm.hotspot.debugger.linux.LinuxAddress.getCompOopHandleAt(LinuxAddress.java:125)
at sun.jvm.hotspot.oops.Oop.getKlassForOopHandle(Oop.java:231)
at sun.jvm.hotspot.oops.ObjectHeap.newOop(ObjectHeap.java:356)
at sun.jvm.hotspot.oops.OopField.getValue(OopField.java:47)
at sun.jvm.hotspot.oops.InstanceKlass.getFields(InstanceKlass.java:337)
at sun.jvm.hotspot.oops.InstanceKlass.getAllFieldsCount(InstanceKlass.java:340)
at sun.jvm.hotspot.oops.InstanceKlass.<init>(InstanceKlass.java:116)
at sun.jvm.hotspot.oops.ObjectHeap.newOop(ObjectHeap.java:367)
at sun.jvm.hotspot.oops.NarrowOopField.getValue(NarrowOopField.java:44)
at sun.jvm.hotspot.oops.Oop.getKlass(Oop.java:93)
at sun.jvm.hotspot.oops.Instance.iterateFields(Instance.java:67)
at sun.jvm.hotspot.oops.Oop.iterate(Oop.java:163)
at sun.jvm.hotspot.tools.PermStat.printClassLoaderStatistics(PermStat.java:192)
at sun.jvm.hotspot.tools.PermStat.run(PermStat.java:66)
at sun.jvm.hotspot.tools.Tool.start(Tool.java:221)
at sun.jvm.hotspot.tools.PermStat.main(PermStat.java:46)
可以根据一定时间间隔,多次打印jmap信息,查看垃圾回收的对象情况。
备注: 这个jmap使用的时候jvm是处在假死状态的,只能在服务瘫痪的时候为了解决问题来使用,否则会造成服务中断。
3. jstack
简介: jstatck 用于查看某个进程下各个线程的状态信息。
在介绍jstatck 具体的指令之前,需要先了解一下线程状态的转换问题,下图形象的描述了线程状态转换:
线程的状态有:new、runnable、running、waiting、timed_waiting、blocked、dead
当执行new Thread(Runnable r)后,新创建出来的线程处于new状态,这种线程不可能执行
当执行thread.start()后,线程处于runnable状态,这种情况下只要得到CPU,就可以开始执行了。runnable状态的线程,会接受JVM的调度,进入running状态,但是具体何时会进入这个状态,是随机不可知的
running状态中的线程最为复杂,可能会进入runnable、waiting、timed_waiting、blocked、dead状态:
如果CPU调度给了别的线程,或者执行了Thread.yield()方法,则进入runnable状态,但是也有可能立刻又进入running状态
如果执行了Thread.sleep(long),或者thread.join(long),或者在锁对象上调用object.wait(long)方法,则会进入timed_waiting状态
如果执行了thread.join(),或者在锁对象上调用了object.wait()方法,则会进入waiting状态
如果进入了同步方法或者同步代码块,没有获取锁对象的话,则会进入blocked状态
处于waiting状态中的线程,如果是因为thread.join()方法进入等待的话,在目标thread执行完毕之后,会回到runnable状态;如果是因为object.wait()方法进入等待的话,在锁对象执行object.notify()或者object.notifyAll()之后会回到runnable状态
处于timed_waiting状态中的线程,和waiting状态中的差不多,只不过是设定时间到了,就会回到runnable状态
处于blocked状态中的线程,只有获取了锁之后,才会脱离阻塞状态
当线程执行完毕,或者抛出了未捕获的异常之后,会进入dead状态,该线程结束。
线程等待状态:
1、不带超时值的 Object.wait
2、不带超时值的 Thread.join
3、LockSupport.park
处于等待状态的线程正等待另一个线程,以执行特定操作。 例如,已经在某一对象上调用了 Object.wait() 的线程正等待另一个线程,以便在该对象上调用 Object.notify() 或 Object.notifyAll()。已经调用了 Thread.join() 的线程正在等待指定线程终止。
TIMED_WAITING
具有指定等待时间的某一等待线程的线程状态。某一线程因为调用以下带有指定正等待时间的方法之一而处于定时等待状态:
1、Thread.sleep
2、带有超时值的 Object.wait
3、带有超时值的 Thread.join
4、LockSupport.parkNanos
5、LockSupport.parkUntil
线程的状态有:new, runnable, running, waiting, blocked, dead
3.1 jstatck -l <PID> 打印关于锁的附加信息
3.2 jstack -F <PID> 在第一条指令没有对应的时候强制打印栈信息
33. jstack -m <PID> 打印java和native c/c++框架的所有栈信息
如果发现机器load过高,可以通过下面步骤来记性处理:
1. 利用top -H p <PID> 来查看哪个线程占用的资源比较高;
2. 再利用jstack <PID> 打印出当前进程中线程堆栈状态;
3. 根据第一步得到的线程ID,在第二部dump出来的文件中查找该线程的详细情况,便可知道问题的所在。
在dump出来的线程信息文件中,存在着线程的多个状态描述:
1. 线程状态为“waiting on condition”, 说明在等待一个条件的发生,来唤醒自己,这里面分为两种:
1.1 java.lang.Thread.State: WAITING (parking):一直等那个条件发生;
1.2 java.lang.Thread.State: TIMED_WAITING (parking或sleeping):定时的,那个条件不到来,也将定时唤醒自己。
2. 线程状态为“waiting for monitor entry” 意味着在等待进入某个临界区(例如:sychronized区域),此时线程状态一般为Blocked. 如果大量的线程被阻塞,可能涉及到全局锁阻塞住了大量线程。
3. 如果大量线程在“waiting on condition” 可能是因为网络读写遇到网络瓶颈或者文件的读写遇见机器IO的瓶颈,导致线程阻塞。
Thread 4092: (state = IN_NATIVE)
Deadlock Detection:
No deadlocks found.
Thread 4166: (state = BLOCKED)
- java.lang.Thread.sleep(long) @bci=0 (Compiled frame; information may be imprecise)
- sun.net.www.http.KeepAliveCache.run() @bci=3, line=172 (Compiled frame)
- java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)
Thread 4092: (state = IN_NATIVE)
- sun.nio.ch.EPollArrayWrapper.epollWait(long, int, long, int) @bci=0 (Compiled frame; information may be imprecise)
- sun.nio.ch.EPollArrayWrapper.poll(long) @bci=18, line=269 (Compiled frame)
- sun.nio.ch.EPollSelectorImpl.doSelect(long) @bci=28, line=79 (Compiled frame)
- sun.nio.ch.SelectorImpl.lockAndDoSelect(long) @bci=37, line=87 (Compiled frame)
- sun.nio.ch.SelectorImpl.select(long) @bci=30, line=98 (Interpreted frame)
- org.apache.mina.transport.socket.nio.SocketConnector$Worker.run() @bci=12, line=362 (Interpreted frame)
- org.apache.mina.util.NamePreservingRunnable.run() @bci=29, line=51 (Interpreted frame)
- java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=95, line=1145 (Compiled frame)
- java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5, line=615 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)
Thread 31627: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Interpreted frame)
- org.apache.hadoop.hbase.ipc.HBaseClient$Connection.waitForWork() @bci=62, line=488 (Interpreted frame)
- org.apache.hadoop.hbase.ipc.HBaseClient$Connection.run() @bci=55, line=533 (Interpreted frame)
4. jstat
jstat 可以对下面的内容进行监控:
1. 类的加载以及卸载情况
2. 查看新生代,老生代及持久代的容量以及使用情况
3. 查看各个代的垃圾收集情况,包括垃圾回收次数,以及垃圾回收站用时间
4. 查看新生代中Eden区以及Survior区中容量以及分配情况
jstat这个指令监控项目比较多,所以在充分理解该指令之前,需要研究一下GC的相关知识,了解各个不同代的转换以及存储关系。
4.1 jstat -class <PID> 查看类加载情况
列名说明
Loaded加载了的类的数量
Bytes加载了的类的大小,单为Kb
Unloaded卸载了的类的数量
Bytes卸载了的类的大小,单为Kb
Time花在类的加载及卸载的时间
sudo -u admin jstat -class 6272
Loaded Bytes Unloaded Bytes Time
16822 34881.5 1 1.6 47.40
4.2 jstat -compiler <PID> 编译器编译情况的统计
列名说明
Compiled编译任务执行的次数
Failed编译任务执行失败的次数
Invalid编译任务非法执行的次数
Time执行编译花费的时间
FailedType最后一次编译失败的编译类型
FailedMethod最后一次编译失败的类名以及方法名
sudo -u admin jstat -compiler 6272
Compiled Failed Invalid Time FailedType FailedMethod
2805 0 0 60.89 0
4.3 jstat -gc <PID> JVM堆中的垃圾收集情况的统计
在使用这个指令的时候,我们需要了解一些 标示代表具体内容。
S0C: 年轻代中第一个survivor(幸存区)的容量(字节)
S1C: 年轻代中第二个survivor(幸存区)的容量 (字节)
S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
EC:年轻代中Eden(伊甸园)的容量 (字节)
EU:年轻代中Eden(伊甸园)目前已使用空间 (字节)
OC:Old代的容量 (字节)
OU:Old代目前已使用空间 (字节)
PC:Perm(持久代)的容量 (字节)
PU:Perm(持久代)目前已使用空间 (字节)
YGC — 从应用程序启动到采样时发生 Young GC 的次数
YGCT– 从应用程序启动到采样时 Young GC 所用的时间(单位秒)
FGC — 从应用程序启动到采样时发生 Full GC 的次数
FGCT– 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
GCT — 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)
sudo -u admin jstat -gc 6272
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
27264.0 27264.0 4345.5 0.0 273152.0 165066.7 983040.0 113007.1 156752.0 108609.5 224 4.942 2 0.273 5.214
4.4 jstat -gccapacity <PID> 新生代,老生代以及持久代的存储容量情况
4.5 jstat -gcnew <PID> 新生代垃圾收集情况
4.6 jstat -gcnewcapacity <PID> 新生代的存储容量情况
4.7 jstat -gcold <PID> 老生代以及持久代发生GC的情况
4.8 jstat -gcpermcapacity <PID> 从应用程序启动到采样发生的FULL GC次数; 持久代的存储容量情况
4.9 jstat -gcutil <PID> 新生代,老生代以及持久代的垃圾收集情况
可以根据定时的打印jstat的信息,来判断full gc的频率,例如:
jstat -gc <PID> 1000, 10 该指令表示每秒打印一次jstat的状态信息,总共打印十次。
如果我们在这个时间间隔内发生的full gc 次数超过了我们设定的阀值,就可以进行报警。
关于jstat的更加详细的说明:
http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstat.html