本文记录一下java队的转储和JVisualVM的用法。
示例代码如下:
1package test.heap;
2
3import java.util.ArrayList;
4import java.util.List;
5
6public class TestHeap {
7 public static void main(String[] args) {
8 List<TestHeap> list = new ArrayList<>();
9 while (true) {
10 list.add(new TestHeap());
11 System.gc();
12 }
13 }
14}
启动参数如下图:
在命令行下执行:jvisualvm,打开这个工具,主界面如下:
- 左上:CPU使用率,GC状态
- 右上:堆的总大小,已使用的堆大小
- 左下:类的监控
- 右下:线程的监控
这个例子中,在一个死循环中新建对象,同时显示调用gc,运行了2个多小时,发现已使用堆的内存在稳步上升,说明有内存泄漏的趋势。
经测试,如果启动参数-Xmx设置的不管是9m,还是10m,到最后分配的最大堆内存是10m。
点击线程页签,界面如下:
这里线程有5个状态:
- 运行
- 休眠
- 等待
- 驻留
- 监视
参考这篇文章Java多线程入门不完全指南顺便复习一下线程的状态。 Thread类定义的线程状态:
- NEW(新建):线程创建后未启动。
1 /**
2 * Thread state for a thread which has not yet started.
3 */
- RUNNABLE(可运行):等待系统资源运行的线程。
1 /**
2 * Thread state for a runnable thread. A thread in the runnable
3 * state is executing in the Java virtual machine but it may
4 * be waiting for other resources from the operating system
5 * such as processor.
6 */
- BLOCKED(阻塞):当一个线程要进入synchronized语句块/方法时,如果没有获取到锁,会变成BLOCKED。或者在调用Object.wait()后,被notify()唤醒,再次进入synchronized语句块/方法时,如果没有获取到锁,会变成BLOCKED。进入阻塞状态是被动的。
1 /**
2 * Thread state for a thread blocked waiting for a monitor lock.
3 * A thread in the blocked state is waiting for a monitor lock
4 * to enter a synchronized block/method or
5 * reenter a synchronized block/method after calling
6 * {@link Object#wait() Object.wait}.
7 */
- WAITING(无限等待):等待其它线程执行后,显示唤醒。调用锁对象的wait()方法并未设置时间、其它线程调用join()方法并未设置时间、调用LockSupport.park()方法都会使当前线程进入此状态。进入等待状态是主动的。
1 /**
2 * Thread state for a waiting thread.
3 * A thread is in the waiting state due to calling one of the
4 * following methods:
5 * <ul>
6 * <li>{@link Object#wait() Object.wait} with no timeout</li>
7 * <li>{@link #join() Thread.join} with no timeout</li>
8 * <li>{@link LockSupport#park() LockSupport.park}</li>
9 * </ul>
10 *
11 * <p>A thread in the waiting state is waiting for another thread to
12 * perform a particular action.
13 *
14 * For example, a thread that has called <tt>Object.wait()</tt>
15 * on an object is waiting for another thread to call
16 * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
17 * that object. A thread that has called <tt>Thread.join()</tt>
18 * is waiting for a specified thread to terminate.
19 */
- TIMED_WAITING(限期等待):等待一段时间后被系统唤醒,不需要显示被唤醒。调用Thread.sleep()方法、调用锁对象的wait()方法并设置时间、其它线程调用join()方法并设置时间、调用LockSupport.parkNanos()方法、调用LockSupport.parkUntil()方法都会使线程进入此状态。
1/**
2 * Thread state for a waiting thread with a specified waiting time.
3 * A thread is in the timed waiting state due to calling one of
4 * the following methods with a specified positive waiting time:
5 * <ul>
6 * <li>{@link #sleep Thread.sleep}</li>
7 * <li>{@link Object#wait(long) Object.wait} with timeout</li>
8 * <li>{@link #join(long) Thread.join} with timeout</li>
9 * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
10 * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
11 * </ul>
12 */
- TERMINATED(结束):线程run()方法执行结束或异常退出后的线程状态。
1 /**
2 * Thread state for a terminated thread.
3 * The thread has completed execution.
4 */
Thread类和监控工具中的线程状态的对应关系如下:
Thread类 | VisualVM |
---|---|
RUNNABLE | 运行 |
TIMED_WAITING (sleeping) | 休眠 |
TIMED_WAITING (on object monitor) WAITING (on object monitor) | 等待 |
TIMED_WAITING (parking) WAITING (parking) | 驻留 |
BLOCKED (on object monitor) | 监视 |
点击线程界面的dump按钮可以查看线程具体的内容:
12020-02-02 17:14:34
2Full thread dump Java HotSpot(TM) Client VM (25.131-b11 mixed mode, sharing):
3
4"RMI TCP Connection(23)-192.168.1.111" #19 daemon prio=5 os_prio=0 tid=0x0536ec00 nid=0x10a0 runnable [0x05c2f000]
5 java.lang.Thread.State: RUNNABLE
6 at java.net.SocketInputStream.socketRead0(Native Method)
7 at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
8 at java.net.SocketInputStream.read(SocketInputStream.java:171)
9 at java.net.SocketInputStream.read(SocketInputStream.java:141)
10 at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
11 at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
12 - locked <0x0492f500> (a java.io.BufferedInputStream)
13 at java.io.FilterInputStream.read(FilterInputStream.java:83)
14 at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:550)
15 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
16 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
17 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$3/29995260.run(Unknown Source)
18 at java.security.AccessController.doPrivileged(Native Method)
19 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
20 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
21 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
22 at java.lang.Thread.run(Thread.java:748)
23
24 Locked ownable synchronizers:
25 - <0x0492d940> (a java.util.concurrent.ThreadPoolExecutor$Worker)
26
27"RMI TCP Connection(idle)" #18 daemon prio=5 os_prio=0 tid=0x0536dc00 nid=0x1f3c waiting on condition [0x00b3f000]
28 java.lang.Thread.State: TIMED_WAITING (parking)
29 at sun.misc.Unsafe.park(Native Method)
30 - parking to wait for <0x046609d0> (a java.util.concurrent.SynchronousQueue$TransferStack)
31 at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
32 at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
33 at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
34 at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:941)
35 at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1066)
36 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
37 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
38 at java.lang.Thread.run(Thread.java:748)
39
40 Locked ownable synchronizers:
41 - None
42
43"RMI TCP Connection(22)-192.168.1.111" #14 daemon prio=5 os_prio=0 tid=0x05528800 nid=0x334 runnable [0x05b8e000]
44 java.lang.Thread.State: RUNNABLE
45 at java.net.SocketInputStream.socketRead0(Native Method)
46 at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
47 at java.net.SocketInputStream.read(SocketInputStream.java:171)
48 at java.net.SocketInputStream.read(SocketInputStream.java:141)
49 at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
50 at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
51 - locked <0x04914ea0> (a java.io.BufferedInputStream)
52 at java.io.FilterInputStream.read(FilterInputStream.java:83)
53 at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:550)
54 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
55 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
56 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$3/29995260.run(Unknown Source)
57 at java.security.AccessController.doPrivileged(Native Method)
58 at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
59 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
60 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
61 at java.lang.Thread.run(Thread.java:748)
62
63 Locked ownable synchronizers:
64 - <0x046e4518> (a java.util.concurrent.ThreadPoolExecutor$Worker)
65
66"JMX server connection timeout 13" #13 daemon prio=5 os_prio=0 tid=0x05515800 nid=0xf88 in Object.wait() [0x0573f000]
67 java.lang.Thread.State: TIMED_WAITING (on object monitor)
68 at java.lang.Object.wait(Native Method)
69 - waiting on <0x046d7538> (a [I)
70 at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168)
71 - locked <0x046d7538> (a [I)
72 at java.lang.Thread.run(Thread.java:748)
73
74 Locked ownable synchronizers:
75 - None
76
77"RMI Scheduler(0)" #12 daemon prio=5 os_prio=0 tid=0x05513000 nid=0x15a8 waiting on condition [0x056ef000]
78 java.lang.Thread.State: TIMED_WAITING (parking)
79 at sun.misc.Unsafe.park(Native Method)
80 - parking to wait for <0x046635f8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
81 at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
82 at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
83 at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
84 at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
85 at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
86 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
87 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
88 at java.lang.Thread.run(Thread.java:748)
89
90 Locked ownable synchronizers:
91 - None
92
93"RMI TCP Accept-0" #10 daemon prio=5 os_prio=0 tid=0x054ebc00 nid=0x17cc runnable [0x055ff000]
94 java.lang.Thread.State: RUNNABLE
95 at java.net.DualStackPlainSocketImpl.accept0(Native Method)
96 at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
97 at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
98 at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
99 - locked <0x046871b8> (a java.net.SocksSocketImpl)
100 at java.net.ServerSocket.implAccept(ServerSocket.java:545)
101 at java.net.ServerSocket.accept(ServerSocket.java:513)
102 at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:52)
103 at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:400)
104 at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:372)
105 at java.lang.Thread.run(Thread.java:748)
106
107 Locked ownable synchronizers:
108 - None
109
110"Service Thread" #8 daemon prio=9 os_prio=0 tid=0x021d5000 nid=0x1e34 runnable [0x00000000]
111 java.lang.Thread.State: RUNNABLE
112
113 Locked ownable synchronizers:
114 - None
115
116"C1 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x021d0800 nid=0xc6c waiting on condition [0x00000000]
117 java.lang.Thread.State: RUNNABLE
118
119 Locked ownable synchronizers:
120 - None
121
122"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x021d6000 nid=0x1acc runnable [0x0529f000]
123 java.lang.Thread.State: RUNNABLE
124 at java.net.SocketInputStream.socketRead0(Native Method)
125 at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
126 at java.net.SocketInputStream.read(SocketInputStream.java:171)
127 at java.net.SocketInputStream.read(SocketInputStream.java:141)
128 at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
129 at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
130 at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
131 - locked <0x045db0d8> (a java.io.InputStreamReader)
132 at java.io.InputStreamReader.read(InputStreamReader.java:184)
133 at java.io.BufferedReader.fill(BufferedReader.java:161)
134 at java.io.BufferedReader.readLine(BufferedReader.java:324)
135 - locked <0x045db0d8> (a java.io.InputStreamReader)
136 at java.io.BufferedReader.readLine(BufferedReader.java:389)
137 at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)
138
139 Locked ownable synchronizers:
140 - None
141
142"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0218f000 nid=0x1ecc waiting on condition [0x00000000]
143 java.lang.Thread.State: RUNNABLE
144
145 Locked ownable synchronizers:
146 - None
147
148"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0218d000 nid=0x10a4 runnable [0x00000000]
149 java.lang.Thread.State: RUNNABLE
150
151 Locked ownable synchronizers:
152 - None
153
154"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x02174000 nid=0xa04 in Object.wait() [0x0514f000]
155 java.lang.Thread.State: WAITING (on object monitor)
156 at java.lang.Object.wait(Native Method)
157 - waiting on <0x04557948> (a java.lang.ref.ReferenceQueue$Lock)
158 at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
159 - locked <0x04557948> (a java.lang.ref.ReferenceQueue$Lock)
160 at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
161 at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
162
163 Locked ownable synchronizers:
164 - None
165
166"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x02117000 nid=0x13c8 in Object.wait() [0x050ff000]
167 java.lang.Thread.State: WAITING (on object monitor)
168 at java.lang.Object.wait(Native Method)
169 - waiting on <0x04556380> (a java.lang.ref.Reference$Lock)
170 at java.lang.Object.wait(Object.java:502)
171 at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
172 - locked <0x04556380> (a java.lang.ref.Reference$Lock)
173 at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
174
175 Locked ownable synchronizers:
176 - None
177
178"main" #1 prio=5 os_prio=0 tid=0x00e7c800 nid=0x1d48 runnable [0x00bbf000]
179 java.lang.Thread.State: RUNNABLE
180 at java.lang.Runtime.gc(Native Method)
181 at java.lang.System.gc(System.java:993)
182 at test.heap.TestHeap.main(TestHeap.java:11)
183
184 Locked ownable synchronizers:
185 - None
186
187"VM Thread" os_prio=2 tid=0x02112c00 nid=0x1d04 runnable
188
189"VM Periodic Task Thread" os_prio=2 tid=0x053b3400 nid=0x14f8 waiting on condition
190
191JNI global references: 237