1.JDK的命令行工具
1.1.jps(JVM Process Status Tool):虚拟机进程状况工具
执行命令如下: jps -l
其他命令:
LVMID:进程的本地虚拟机唯一ID (Local Virtual Machine Identifier,LVMID)
jps -q 和 jps -m:
jps -v
jps -l
1.2.jstat(JVM Statistics Monitoring Tool):虚拟机统计信息监视工具
JavaGC各种变量意义:
S0C:年轻代中第一个survivor(幸存区)的容量 (kb)
S1C:年轻代中第二个survivor(幸存区)的容量 (kb)
S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (kb)
S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (kb)
EC:年轻代中Eden(伊甸园)的容量 (kb)
EU:年轻代中Eden(伊甸园)目前已使用空间 (kb)
OC:Old代的容量 (kb)
OU:Old代目前已使用空间 (kb)
PC:Perm(持久代)的容量 (kb)
PU:Perm(持久代)目前已使用空间 (kb)
YGC:从应用程序启动到采样时年轻代中gc次数
YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)
FGC:从应用程序启动到采样时old代(全gc)gc次数
FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT:从应用程序启动到采样时gc用的总时间(s)
NGCMN:年轻代(young)中初始化(最小)的大小 (kb)
NGCMX:年轻代(young)的最大容量 (kb)
NGC:年轻代(young)中当前的容量 (kb)
OGCMN:old代中初始化(最小)的大小 (kb)
OGCMX:old代的最大容量 (kb)
OGC:old代当前新生成的容量 (kb)
PGCMN:perm代中初始化(最小)的大小 (kb)
PGCMX:perm代的最大容量 (kb)
PGC:perm代当前新生成的容量 (kb)
S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比
S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比
E:年轻代中Eden(伊甸园)已使用的占当前容量百分比
O:old代已使用的占当前容量百分比
P:perm代已使用的占当前容量百分比
S0CMX:年轻代中第一个survivor(幸存区)的最大容量 (kb)
S1CMX :年轻代中第二个survivor(幸存区)的最大容量 (kb)
ECMX:年轻代中Eden(伊甸园)的最大容量 (kb)
DSS:当前需要survivor(幸存区)的容量 (kb)(Eden区已满)
TT: 持有次数限制
MTT : 最大持有次数限制
jstat命令格式为:
jstat [ option vmid [ interval [s|ms] [count] ] ]
选项option代表着用户希望查询的虚拟机信息,主要分为3类:类装载、 垃圾收集、 运行
期编译状况
对于命令格式中的VMID与LVMID需要特别说明一下:如果是本地虚拟机进程,VMID与
LVMID是一致的,如果是远程虚拟机进程,那VMID的格式应当是
[ protocol:] [//] lvmid [ @hostname [:port ] /servername ]
参数interval和count代表查询间隔和次数,如果省略这两个参数,说明只查询一次。 假设
需要每250毫秒查询一次进程2764垃圾收集状况,一共查询20次,那命令应当是:
jstat -gc 2764 250 20
jstat各种实例如下:在最新的jdk版本(1.8.0_181)中,已经没有 -gcpermcapacity 这个 option 了
1.3.jinfo(Configuration Info for Java):Java配置信息工具
jinfo(Configuration Info for Java)的作用是实时地查看和调整虚拟机各项参数。 使用jps
命令的-v参数可以查看虚拟机启动时显式指定的参数列表,但如果想知道未被显式指定的参
数的系统默认值,除了去找资料外,就只能使用jinfo的-flag选项进行查询了(如果只限于
JDK 1.6或以上版本的话,使用java-XX:+PrintFlagsFinal查看参数默认值也是一个很好的选
择),jinfo还可以使用-sysprops选项把虚拟机进程的System.getProperties()的内容打印出
来。 这个命令在JDK 1.5时期已经随着Linux版的JDK发布,当时只提供了信息查询的功
能,JDK 1.6之后,jinfo在Windows和Linux平台都有提供,并且加入了运行期修改参数的能
力,可以使用-flag[+|-]name或者-flag name=value修改一部分运行期可写的虚拟机参数值。
JDK 1.6中,jinfo对于Windows平台功能仍然有较大限制,只提供了最基本的-flag选项。
jinfo命令格式:
jinfo [option] pid
jinfo实例如下:
1.4.jmap(Memory Map for Java):Java内存映像工具
jmap(Memory Map for Java)命令用于生成堆转储快照(一般称为heapdump或dump文
件)。 如果不使用jmap命令,要想获取Java堆转储快照,还有一些比较“暴力”的手段:譬如
在第2章中用过的-XX:+HeapDumpOnOutOfMemoryError参数,可以让虚拟机在OOM异常出
现之后自动生成dump文件,通过-XX:+HeapDumpOnCtrlBreak参数则可以使用[Ctrl]+[Break]
键让虚拟机生成dump文件,又或者在Linux系统下通过Kill-3命令发送进程退出信号“吓唬”一
下虚拟机,也能拿到dump文件。
jmap的作用并不仅仅是为了获取dump文件,它还可以查询finalize执行队列、 Java堆和永
久代的详细信息,如空间使用率、 当前用的是哪种收集器等。
和jinfo命令一样,jmap有不少功能在Windows平台下都是受限的,除了生成dump文件的-
dump选项和用于查看每个类的实例、 空间占用统计的-histo选项在所有操作系统都提供之
外,其余选项都只能在Linux/Solaris下使用。
jmap命令格式:
jmap [option] vmid
使用实例:
1.5.jhat(JVM Heap Analysis Tool):虚拟机堆转储快照分析工具
Sun JDK提供jhat(JVM Heap Analysis Tool)命令与jmap搭配使用,来分析jmap生成的堆
转储快照。 jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,可以在
浏览器中查看。 不过实事求是地说,在实际工作中,除非笔者手上真的没有别的工具可用,
否则一般都不会去直接使用jhat命令来分析dump文件,主要原因有二:一是一般不会在部署
应用程序的服务器上直接分析dump文件,即使可以这样做,也会尽量将dump文件复制到其
他机器[1]上进行分析,因为分析工作是一个耗时而且消耗硬件资源的过程,既然都要在其他
机器进行,就没有必要受到命令行工具的限制了;另一个原因是jhat的分析功能相对来说比
较简陋,后文将会介绍到的VisualVM,以及专业用于分析dump文件的Eclipse Memory
Analyzer、 IBM HeapAnalyzer[2]等工具,都能实现比jhat更强大更专业的分析功能。 代码清单4-
3演示了使用jhat分析4.2.4节中采用jmap生成的Eclipse IDE的内存快照文件。
代码清单4-3 使用jhat分析dump文件
C:\Users\IcyFenix>jhat eclipse.bin
Reading from eclipse.bin……
Dump file created Fri Nov 19 22:07:21 CST 2010
Snapshot read,resolving……
Resolving 1225951 objects……
Chasing references,expect 245 dots……
Eliminating duplicate references……
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
屏幕显示“Server is ready.”的提示后,用户在浏览器中键入http://localhost:7000/就可以
看到分析结果,如图4-3所示
1.6.jstack(Stack Trace for Java):Java堆栈跟踪工具
jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为
threaddump或者javacore文件)。 线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈
的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、 死循
环、 请求外部资源导致的长时间等待等都是导致线程长时间停顿的常见原因。 线程出现停顿
的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些
什么事情,或者等待着什么资源
jstack命令格式:
jstack [option] vmid
option如下图所示:
使用案例:
C:\Program Files\Java\jdk1.8.0_181\bin>jstack -l 12344
2019-05-10 14:04:50
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.181-b13 mixed mode):
"DestroyJavaVM" #15 prio=5 os_prio=0 tid=0x0000000003c6f800 nid=0x36a8 waiting o
n condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"JPS event loop" #10 prio=5 os_prio=0 tid=0x0000000018886000 nid=0x2b2c runnable
[0x0000000019a8f000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(WindowsSelectorImpl.j
ava:296)
at sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(WindowsSelector
Impl.java:278)
at sun.nio.ch.WindowsSelectorImpl.doSelect(WindowsSelectorImpl.java:159)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
- locked <0x00000000d4e24260> (a io.netty.channel.nio.SelectedSelectionK
eySet)
- locked <0x00000000d4e30a70> (a java.util.Collections$UnmodifiableSet)
- locked <0x00000000d4e25288> (a sun.nio.ch.WindowsSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
at io.netty.channel.nio.SelectedSelectionKeySetSelector.select(SelectedS
electionKeySetSelector.java:62)
at io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:753)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:408)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThread
EventExecutor.java:897)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x0000000016feb800 nid=0x570 run
nable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C1 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x0000000016fe8800 nid=0x325
8 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x0000000016fe7000 nid=0x354
4 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x0000000015aaf000 nid=0x254
0 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000015aac000 nid=0x320c w
aiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0000000015aa7800 nid=0x3740
runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x0000000015a92000 nid=0x310c in Obje
ct.wait() [0x0000000016bce000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d501cf60> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x00000000d501cf60> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
Locked ownable synchronizers:
- None
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000015a4b000 nid=0x395
0 in Object.wait() [0x0000000016f6f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d50bddf8> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x00000000d50bddf8> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=2 tid=0x0000000015a42800 nid=0x36ac runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000003c84000 nid=0x30ec runn
able
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000003c85800 nid=0x33c8 runn
able
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000003c87000 nid=0x3848 runn
able
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000003c88800 nid=0x3958 runn
able
"VM Periodic Task Thread" os_prio=2 tid=0x0000000017003800 nid=0x313c waiting on
condition
JNI global references: 265
1.7.HSDIS:JIT生成代码反汇编
在Java虚拟机规范中,详细描述了虚拟机指令集中每条指令的执行过程、 执行前后对操
作数栈、 局部变量表的影响等细节。 这些细节描述与Sun的早期虚拟机(Sun Classic VM)高
度吻合,但随着技术的发展,高性能虚拟机真正的细节实现方式已经渐渐与虚拟机规范所描
述的内容产生了越来越大的差距,虚拟机规范中的描述逐渐成了虚拟机实现的“概念模
型”——即实现只能保证规范描述等效。 基于这个原因,我们分析程序的执行语义问题(虚
拟机做了什么)时,在字节码层面上分析完全可行,但分析程序的执行行为问题(虚拟机是
怎样做的、 性能如何)时,在字节码层面上分析就没有什么意义了,需要通过其他方式解
决。
分析程序如何执行,通过软件调试工具(GDB、 Windbg等)来断点调试是最常见的手
段,但是这样的调试方式在Java虚拟机中会遇到很大困难,因为大量执行代码是通过JIT编译
器动态生成到CodeBuffer中的,没有很简单的手段来处理这种混合模式的调试(不过相信虚
拟机开发团队内部肯定是有内部工具的)。 因此,不得不通过一些特别的手段来解决问题,
基于这种背景,本节的主角——HSDIS插件就正式登场了。
HSDIS是一个Sun官方推荐的HotSpot虚拟机JIT编译代码的反汇编插件,它包含在HotSpot
虚拟机的源码之中,但没有提供编译后的程序。 在Project Kenai的网站[1]也可以下载到单独的
源码。 它的作用是让HotSpot的-XX:+PrintAssembly指令调用它来把动态生成的本地代码还
原为汇编代码输出,同时还生成了大量非常有价值的注释,这样我们就可以通过输出的代码
来分析问题。 读者可以根据自己的操作系统和CPU类型从Project Kenai的网站上下载编译好
的插件,直接放到JDK_HOME/jre/bin/client和JDK_HOME/jre/bin/server目录中即可。 如果没
有找到所需操作系统(譬如Windows的就没有)的成品,那就得自己使用源码编译一下[2]。
还需要注意的是,如果读者使用的是Debug或者FastDebug版的HotSpot,那可以直接通
过-XX:+PrintAssembly指令使用插件;如果使用的是Product版的HotSpot,那还要额外加入
一个-XX:+UnlockDiagnosticVMOptions参数。 笔者以代码清单4-6中的简单测试代码为例演
示一下这个插件的使用
代码实例:
public class Bar {
int a =1;
static int b =2;
public int sum(int c){
return a+b+c;
}
public static void main(String[] args) {
new Bar().sum(2);
}
}
编译命令:
java -XX:+PrintAssembly -Xcomp -XX:CompileCommand=dontinline,*Bar.sum -XX:CompileCommand=compileonly,*Bar.sum test.Bar
结果输出:
[Disassembling for mach='i386']
[Entry Point]
[Constants]
#{method}'sum''(I)I'in'test/Bar'
#this:ecx='test/Bar'
#parm0:edx=int
#[sp+0x20](sp of caller)
……
0x01cac407:cmp 0x4(%ecx),%eax
0x01cac40a:jne 0x01c6b050;{runtime_call}
[Verified Entry Point]
0x01cac410:mov%eax,-0x8000(%esp)
0x01cac417:push%ebp
0x01cac418:sub$0x18,%esp;*aload_0
;-test.Bar:sum@0(line 8)
;block B0[0,10]
0x01cac41b:mov 0x8(%ecx),%eax;*getfield a
;-test.Bar:sum@1(line 8)
0x01cac41e:mov$0x3d2fad8,%esi;{oop(a
'java/lang/Class'='test/Bar')}
0x01cac423:mov 0x68(%esi),%esi;*getstatic b
;-test.Bar:sum@4(line 8)
0x01cac426:add%esi,%eax
0x01cac428:add%edx,%eax
0x01cac42a:add$0x18,%esp
0x01cac42d:pop%ebp
0x01cac42e:test%eax,0x2b0100;{poll_return}
0x01cac434:ret
对输出解释:
1)mov%eax,-0x8000(%esp):检查栈溢。
2)push%ebp:保存上一栈帧基址。
3)sub$0x18,%esp:给新帧分配空间。
4)mov 0x8(%ecx),%eax:取实例变量a,这里0x8(%ecx)就是ecx+0x8的意思,前
面“[Constants]”节中提示了“this:ecx='test/Bar'”,即ecx寄存器中放的就是this对象的地址。 偏
移0x8是越过this对象的对象头,之后就是实例变量a的内存位置。 这次是访问“Java堆”中的数
据。
5)mov$0x3d2fad8,%esi:取test.Bar在方法区的指针。
6)mov 0x68(%esi),%esi:取类变量b,这次是访问“方法区”中的数据。
7)add%esi,%eax和add%edx,%eax:做两次加法,求a+b+c的值,前面的代码把a放在
eax中,把b放在esi中,而c在[Constants]中提示了,“parm0:edx=int”,说明c在edx中。
8)add$0x18,%esp:撤销栈帧。
9)pop%ebp:恢复上一栈帧。
10)test%eax,0x2b0100:轮询方法返回处的SafePoint。
11)ret:方法返回。
2.JDK的可视化工具
JDK中除了提供大量的命令行工具外,还有两个功能强大的可视化工具:
JConsole和VisualVM,这两个工具是JDK的正式成员,没有被贴上“unsupported and experimental”的标签。
2.1 JConsole:Java监视与管理控制台
2.1.1 启动JConsole (相当于jps命令)
通过JDK/bin目录下的“jconsole.exe”启动JConsole后,将自动搜索出本机运行的所有虚拟
机进程,不需要用户自己再使用jps来查询了,如下图示。 双击选择其中一个进程即可开
始监控,也可以使用下面的“远程进程”功能来连接远程服务器,对远程虚拟机进行监控。
2.1.2.内存监控 (相当于 jstat命令)
两个问题:
1)虚拟机启动参数只限制了Java堆为100MB,没有指定-Xmn参数,能否从监控图中估
计出新生代有多大?
下图所示:
答案:
新生代内存:Eden区+survivor0+survivor1 关系为8:1:1
显示Eden空间为27 328KB,因为没有设置-XX:SurvivorRadio参数,
所以Eden与Survivor空间比例为默认值8:1,整个新生代空间大约为27 328KB×125%=34
160KB。
2)为何执行了System.gc()之后,上图老年代的柱状图仍然显示峰值状态,代
码需要如何调整才能让System.gc()回收掉填充到堆中的对象?
代码如下:该如何调整:
public class OOMObject {
public byte[] placeholder = new byte[64 * 1024];
public static void fillHeap(int num) throws InterruptedException {
/**
* 内存占位符对象,一个OOMObject大约占64KB
*/
List<OOMObject> list = new ArrayList<OOMObject>();
for (int i = 0; i < num; i++) {
//稍作延时,令监视曲线的变化更加明显
Thread.sleep(50);
list.add(new OOMObject());
}
System.gc();
}
public static void main(String[] args) throws Exception {
fillHeap(1000);
}
}
更改成如下代码可以解决:
public class OOMObject {
public byte[] placeholder = new byte[64 * 1024];
public static void fillHeap(int num) throws InterruptedException {
/**
* 内存占位符对象,一个OOMObject大约占64KB
*/
List<OOMObject> list = new ArrayList<OOMObject>();
for (int i = 0; i < num; i++) {
//稍作延时,令监视曲线的变化更加明显
Thread.sleep(50);
list.add(new OOMObject());
}
}
public static void main(String[] args) throws Exception {
fillHeap(1000);
System.gc();
}
}
2.1.3 .线程监控 (相当于jstack命令)
2.2 VisualVM(All-in-One Java Troubleshooting Tool):多合一故障处理工具
VisualVM(All-in-One Java Troubleshooting Tool)是到目前为止随JDK发布的功能最强大
的运行监视和故障处理程序,并且可以预见在未来一段时间内都是官方主力发展的虚拟机故
障处理工具。 官方在VisualVM的软件说明中写上了“All-in-One”的描述字样,预示着它除了
运行监视、 故障处理外,还提供了很多其他方面的功能。 如性能分析
(Profiling),VisualVM的性能分析功能甚至比起JProfiler、 YourKit等专业且收费的Profiling
工具都不会逊色多少,而且VisualVM的还有一个很大的优点:不需要被监视的程序基于特殊
Agent运行,因此它对应用程序的实际性能的影响很小,使得它可以直接应用在生产环境
中。 这个优点是JProfiler、 YourKit等工具无法与之媲美的。
VisualVM可以做到:
显示虚拟机进程以及进程的配置、 环境信息(jps、 jinfo)。
监视应用程序的CPU、 GC、 堆、 方法区以及线程的信息(jstat、 jstack)。
dump以及分析堆转储快照(jmap、 jhat)。
方法级的程序运行性能分析,找出被调用最多、 运行时间最长的方法。
离线程序快照:收集程序的运行时配置、 线程dump、 内存dump等信息建立一个快照,
可以将快照发送开发者处进行Bug反馈。
其他plugins的无限的可能性……
将上面的OOMObject类启动之后,可以在Visual VM中看到相关信息:
线程dump:
2019-05-10 15:36:51
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.181-b13 mixed mode):
"JMX server connection timeout 17" #17 daemon prio=5 os_prio=0 tid=0x00000000202ec800 nid=0x3e08 in Object.wait()
[0x0000000020acf000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076cf0f230> (a [I)
at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168)
- locked <0x000000076cf0f230> (a [I)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"RMI Scheduler(0)" #16 daemon prio=5 os_prio=0 tid=0x00000000203ad800 nid=0xabc waiting on condition
[0x0000000020d4f000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x000000076c59b2d8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"RMI TCP Connection(1)-10.108.3.87" #15 daemon prio=5 os_prio=0 tid=0x00000000202fe800 nid=0x3f1c runnable
[0x000000001f81e000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
- locked <0x000000076ccf2d98> (a java.io.BufferedInputStream)
at java.io.FilterInputStream.read(FilterInputStream.java:83)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:555)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$3/1511885133.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- <0x000000076c90b218> (a java.util.concurrent.ThreadPoolExecutor$Worker)
"RMI TCP Accept-0" #14 daemon prio=5 os_prio=0 tid=0x00000000202d5000 nid=0x3f14 runnable [0x0000000020bff000]
java.lang.Thread.State: RUNNABLE
at java.net.DualStackPlainSocketImpl.accept0(Native Method)
at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
- locked <0x000000076c8be5f8> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(ServerSocket.java:545)
at java.net.ServerSocket.accept(ServerSocket.java:513)
at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:52)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:405)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:377)
at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers:
- None
"Service Thread" #12 daemon prio=9 os_prio=0 tid=0x000000001ee6a000 nid=0x304c runnable
[0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C1 CompilerThread2" #11 daemon prio=9 os_prio=2 tid=0x000000001ef1c000 nid=0x3224 waiting on condition
[0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread1" #10 daemon prio=9 os_prio=2 tid=0x000000001eedd000 nid=0x3e34 waiting on condition
[0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" #9 daemon prio=9 os_prio=2 tid=0x000000001eed0800 nid=0x3e2c waiting on condition
[0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"JDWP Command Reader" #8 daemon prio=10 os_prio=0 tid=0x000000001ed14000 nid=0x3d58 runnable
[0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"JDWP Event Helper Thread" #7 daemon prio=10 os_prio=0 tid=0x000000001ed12800 nid=0x3e44 runnable
[0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"JDWP Transport Listener: dt_socket" #6 daemon prio=10 os_prio=0 tid=0x000000001d7ac000 nid=0x8bc runnable
[0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001ece9800 nid=0x3e88 waiting on condition
[0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001ece8800 nid=0x3e6c runnable
[0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001d78d800 nid=0x3d34 in Object.wait()
[0x000000001ecde000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076b588ed0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
- locked <0x000000076b588ed0> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
Locked ownable synchronizers:
- None
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001d746000 nid=0x3fac in Object.wait()
[0x000000001eadf000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000076b586bf8> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x000000076b586bf8> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
Locked ownable synchronizers:
- None
"main" #1 prio=5 os_prio=0 tid=0x0000000003b2b800 nid=0x3bdc waiting on condition [0x0000000003e2f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.atguigu.jvm.gc.OOMObject.fillHeap(OOMObject.java:27)
at com.atguigu.jvm.gc.OOMObject.main(OOMObject.java:34)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=2 tid=0x000000001d73e800 nid=0x3fe8 runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000003b40000 nid=0x1188 runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000003b41800 nid=0x3e04 runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000003b43000 nid=0x3df8 runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000003b44800 nid=0x3df4 runnable
"VM Periodic Task Thread" os_prio=2 tid=0x000000001efd8800 nid=0x3d30 waiting on condition
JNI global references: 5251