Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/javax/management/monitor/GaugeMonitorDeadlockTest.java
41152 views
1
/*
2
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/*
25
* @test
26
* @bug 6303187
27
* @summary Test that no locks are held when a monitor attribute is sampled
28
* or notif delivered.
29
* @author Eamonn McManus
30
*
31
* @library /test/lib
32
*
33
* @run clean GaugeMonitorDeadlockTest
34
* @run build GaugeMonitorDeadlockTest
35
* @run main GaugeMonitorDeadlockTest 1
36
* @run main GaugeMonitorDeadlockTest 2
37
* @run main GaugeMonitorDeadlockTest 3
38
* @run main GaugeMonitorDeadlockTest 4
39
*/
40
41
import java.lang.management.ManagementFactory;
42
import java.lang.management.ThreadInfo;
43
import java.lang.management.ThreadMXBean;
44
import java.util.concurrent.atomic.AtomicInteger;
45
import javax.management.JMX;
46
import javax.management.MBeanServer;
47
import javax.management.Notification;
48
import javax.management.NotificationListener;
49
import javax.management.ObjectName;
50
import javax.management.monitor.GaugeMonitor;
51
import javax.management.monitor.GaugeMonitorMBean;
52
53
import jdk.test.lib.Utils;
54
55
public class GaugeMonitorDeadlockTest {
56
private static enum When {IN_GET_ATTRIBUTE, IN_NOTIFY};
57
private static long checkingTime;
58
59
public static void main(String[] args) throws Exception {
60
if (args.length != 1)
61
throw new Exception("Arg should be test number");
62
checkingTime = Utils.adjustTimeout(1000); // default 1s timeout
63
System.out.println("=== checkingTime = " + checkingTime + "ms");
64
65
int testNo = Integer.parseInt(args[0]) - 1;
66
TestCase test = testCases[testNo];
67
System.out.println("Test: " + test.getDescription());
68
test.run();
69
System.out.println("Test passed");
70
}
71
72
private static abstract class TestCase {
73
TestCase(String description, When when) {
74
this.description = description;
75
this.when = when;
76
}
77
78
void run() throws Exception {
79
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
80
final ObjectName observedName = new ObjectName("a:b=c");
81
final ObjectName monitorName = new ObjectName("a:type=Monitor");
82
mbs.registerMBean(new GaugeMonitor(), monitorName);
83
final GaugeMonitorMBean monitorProxy =
84
JMX.newMBeanProxy(mbs, monitorName, GaugeMonitorMBean.class);
85
final TestMBean observedProxy =
86
JMX.newMBeanProxy(mbs, observedName, TestMBean.class);
87
88
final Runnable sensitiveThing = new Runnable() {
89
public void run() {
90
doSensitiveThing(monitorProxy, observedName);
91
}
92
};
93
94
final Runnable nothing = new Runnable() {
95
public void run() {}
96
};
97
98
final Runnable withinGetAttribute =
99
(when == When.IN_GET_ATTRIBUTE) ? sensitiveThing : nothing;
100
101
mbs.registerMBean(new Test(withinGetAttribute), observedName);
102
monitorProxy.addObservedObject(observedName);
103
monitorProxy.setObservedAttribute("Thing");
104
monitorProxy.setThresholds(105, 100);
105
monitorProxy.setGranularityPeriod(10L); // 10 ms
106
monitorProxy.setNotifyHigh(true);
107
monitorProxy.setNotifyLow(true);
108
109
System.out.println("=== Waiting observedProxy.getGetCount() to be "
110
+ "changed, presumable deadlock if timeout?");
111
final int initGetCount = observedProxy.getGetCount();
112
monitorProxy.start();
113
114
long checkedTime = System.currentTimeMillis();
115
long nowTime;
116
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
117
while (observedProxy.getGetCount() == initGetCount) {
118
Thread.sleep(100);
119
120
nowTime = System.currentTimeMillis();
121
if (nowTime - checkedTime >= checkingTime) {
122
System.out.println("=== Checking deadlocked ...");
123
if (threadMXBean.findDeadlockedThreads() != null) {
124
for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
125
System.out.println(info);
126
}
127
throw new Error("Found deadlocked threads: "
128
+ threadMXBean.findDeadlockedThreads().length);
129
}
130
checkedTime = System.currentTimeMillis();
131
}
132
}
133
134
// This won't show up as a deadlock in CTRL-\ or in
135
// ThreadMXBean.findDeadlockedThreads(), because they don't
136
// see that thread A is waiting for thread B (B.join()), and
137
// thread B is waiting for a lock held by thread A
138
139
// Now we know the monitor has observed the initial value,
140
// so if we want to test notify behaviour we can trigger by
141
// exceeding the threshold.
142
if (when == When.IN_NOTIFY) {
143
final Thread testedThread = new Thread(sensitiveThing);
144
final AtomicInteger notifCount = new AtomicInteger();
145
final NotificationListener listener = new NotificationListener() {
146
public void handleNotification(Notification n, Object h) {
147
testedThread.start();
148
try {
149
testedThread.join();
150
} catch (InterruptedException e) {
151
throw new RuntimeException(e);
152
}
153
notifCount.incrementAndGet();
154
}
155
};
156
mbs.addNotificationListener(monitorName, listener, null, null);
157
observedProxy.setThing(1000);
158
System.out.println("=== Waiting notifications, presumable "
159
+ "deadlock if timeout?");
160
long startTime = System.currentTimeMillis();
161
checkedTime = startTime;
162
while (notifCount.get() == 0) {
163
Thread.sleep(100);
164
165
nowTime = System.currentTimeMillis();
166
if (nowTime - checkedTime >= checkingTime) {
167
System.out.println("=== Checking the thread state ...");
168
if (testedThread.isAlive()) {
169
System.out.println("=== Waiting testedThread to die "
170
+ "after " + (nowTime - startTime) + "ms");
171
172
ThreadInfo tinfo = threadMXBean.getThreadInfo(testedThread.getId());
173
if (Thread.State.BLOCKED.equals(tinfo.getThreadState())) {
174
for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
175
System.out.println(info);
176
}
177
} else {
178
System.out.println(tinfo);
179
}
180
} else {
181
System.out.println("=== The testedThread is dead as wished, "
182
+ "the test must be passed soon.");
183
}
184
checkedTime = System.currentTimeMillis();
185
}
186
}
187
}
188
}
189
190
abstract void doSensitiveThing(GaugeMonitorMBean monitorProxy,
191
ObjectName observedName);
192
193
String getDescription() {
194
return description;
195
}
196
197
private final String description;
198
private final When when;
199
}
200
201
private static final TestCase[] testCases = {
202
new TestCase("Remove monitored MBean within monitored getAttribute",
203
When.IN_GET_ATTRIBUTE) {
204
@Override
205
void doSensitiveThing(GaugeMonitorMBean monitorProxy,
206
ObjectName observedName) {
207
monitorProxy.removeObservedObject(observedName);
208
}
209
},
210
new TestCase("Stop monitor within monitored getAttribute",
211
When.IN_GET_ATTRIBUTE) {
212
@Override
213
void doSensitiveThing(GaugeMonitorMBean monitorProxy,
214
ObjectName observedName) {
215
monitorProxy.stop();
216
}
217
},
218
new TestCase("Remove monitored MBean within threshold listener",
219
When.IN_NOTIFY) {
220
@Override
221
void doSensitiveThing(GaugeMonitorMBean monitorProxy,
222
ObjectName observedName) {
223
monitorProxy.removeObservedObject(observedName);
224
}
225
},
226
new TestCase("Stop monitor within threshold listener",
227
When.IN_NOTIFY) {
228
@Override
229
void doSensitiveThing(GaugeMonitorMBean monitorProxy,
230
ObjectName observedName) {
231
monitorProxy.stop();
232
}
233
},
234
};
235
236
public static interface TestMBean {
237
public int getThing();
238
public void setThing(int thing);
239
public int getGetCount();
240
}
241
242
public static class Test implements TestMBean {
243
public Test(Runnable runWithinGetAttribute) {
244
this.runWithinGetAttribute = runWithinGetAttribute;
245
}
246
247
public int getThing() {
248
Thread t = new Thread(runWithinGetAttribute);
249
t.start();
250
try {
251
t.join();
252
} catch (InterruptedException e) {
253
throw new RuntimeException(e);
254
}
255
getCount++;
256
return thing;
257
}
258
259
public void setThing(int thing) {
260
this.thing = thing;
261
}
262
263
public int getGetCount() {
264
return getCount;
265
}
266
267
private final Runnable runWithinGetAttribute;
268
private volatile int getCount;
269
private volatile int thing;
270
}
271
}
272
273