blob: bd10c432f349033d5702e80a41fc3ac25b039a21 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 * @test
26 * @bug 5086470 6358247
27 * @summary Basic Test for ThreadMXBean.dumpAllThreads(false, true)
28 * and getThreadInfo of customized JSR-166 synchronizers.
29 * @author Mandy Chung
30 *
31 * @build Barrier
32 * @build ThreadDump
33 * @run main MyOwnSynchronizer
34 */
35
36import java.lang.management.*;
37import java.util.*;
38import java.util.concurrent.locks.*;
39import java.util.concurrent.TimeUnit;
40import java.io.*;
41
42public class MyOwnSynchronizer {
43 static ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
44 static Mutex mutex = new Mutex();
45 static MyThread thread = new MyThread();
46 public static void main(String[] argv) throws Exception {
47 if (!mbean.isSynchronizerUsageSupported()) {
48 System.out.println("Monitoring of synchronizer usage not supported");
49 return;
50 }
51
52 thread.setDaemon(true);
53 thread.start();
54
55 // wait until myThread acquires mutex
56 while (!mutex.isLocked()) {
57 try {
58 Thread.sleep(100);
59 } catch (InterruptedException e) {
60 throw new RuntimeException(e);
61 }
62 }
63
64 ThreadDump.threadDump();
65 // Test dumpAllThreads with locked synchronizers
66 ThreadInfo[] tinfos = mbean.dumpAllThreads(false, true);
67 for (ThreadInfo ti : tinfos) {
68 MonitorInfo[] monitors = ti.getLockedMonitors();
69 if (monitors.length != 0) {
70 throw new RuntimeException("Name: " + ti.getThreadName() +
71 " has non-empty locked monitors = " + monitors.length);
72 }
73 LockInfo[] syncs = ti.getLockedSynchronizers();
74 if (ti.getThreadId() == thread.getId()) {
75 thread.checkLockedSyncs(ti, syncs);
76 }
77 }
78
79 // Test getThreadInfo with locked synchronizers
80 tinfos = mbean.getThreadInfo(new long[] {thread.getId()}, false, true);
81 if (tinfos.length != 1) {
82 throw new RuntimeException("getThreadInfo() returns " +
83 tinfos.length + " ThreadInfo objects. Expected 0.");
84 }
85 ThreadInfo ti = tinfos[0];
86 if (ti.getLockedMonitors().length != 0) {
87 throw new RuntimeException("Name: " + ti.getThreadName() +
88 " has non-empty locked monitors = " +
89 ti.getLockedMonitors().length);
90 }
91 thread.checkLockedSyncs(ti, ti.getLockedSynchronizers());
92
93 System.out.println("Test passed");
94 }
95
96 static class Mutex implements Lock, java.io.Serializable {
97
98 // Our internal helper class
99 class Sync extends AbstractQueuedSynchronizer {
100 // Report whether in locked state
101 protected boolean isHeldExclusively() {
102 return getState() == 1;
103 }
104
105 // Acquire the lock if state is zero
106 public boolean tryAcquire(int acquires) {
107 assert acquires == 1; // Otherwise unused
108 if (compareAndSetState(0, 1)) {
109 setExclusiveOwnerThread(Thread.currentThread());
110 return true;
111 }
112 return false;
113 }
114
115 // Release the lock by setting state to zero
116 protected boolean tryRelease(int releases) {
117 assert releases == 1; // Otherwise unused
118 if (getState() == 0) throw new IllegalMonitorStateException();
119 setExclusiveOwnerThread(null);
120 setState(0);
121 return true;
122 }
123
124 // Provide a Condition
125 Condition newCondition() { return new ConditionObject(); }
126
127 // Deserialize properly
128 private void readObject(ObjectInputStream s)
129 throws IOException, ClassNotFoundException {
130 s.defaultReadObject();
131 setState(0); // reset to unlocked state
132 }
133 }
134
135 // The sync object does all the hard work. We just forward to it.
136 private final Sync sync = new Sync();
137
138 public void lock() { sync.acquire(1); }
139 public boolean tryLock() { return sync.tryAcquire(1); }
140 public void unlock() { sync.release(1); }
141 public Condition newCondition() { return sync.newCondition(); }
142 public boolean isLocked() { return sync.isHeldExclusively(); }
143 public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
144 public void lockInterruptibly() throws InterruptedException {
145 sync.acquireInterruptibly(1);
146 }
147 public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
148 return sync.tryAcquireNanos(1, unit.toNanos(timeout));
149 }
150
151 public AbstractOwnableSynchronizer getSync() { return sync; }
152 }
153
154 static class MyThread extends Thread {
155 public MyThread() {
156 super("MyThread");
157 }
158 public void run() {
159 mutex.lock();
160 Object o = new Object();
161 synchronized(o) {
162 try {
163 o.wait();
164 } catch (InterruptedException e) {
165 throw new RuntimeException(e);
166 }
167 }
168 }
169 int OWNED_SYNCS = 1;
170 void checkLockedSyncs(ThreadInfo info, LockInfo[] syncs) {
171 if (!getName().equals(info.getThreadName())) {
172 throw new RuntimeException("Name: " + info.getThreadName() +
173 " not matched. Expected: " + getName());
174 }
175
176 if (syncs.length != OWNED_SYNCS) {
177 throw new RuntimeException("Number of locked syncs = " +
178 syncs.length +
179 " not matched. Expected: " + OWNED_SYNCS);
180 }
181 AbstractOwnableSynchronizer s = mutex.getSync();
182 String lockName = s.getClass().getName();
183 int hcode = System.identityHashCode(s);
184 if (!lockName.equals(syncs[0].getClassName())) {
185 throw new RuntimeException("LockInfo : " + syncs[0] +
186 " class name not matched. Expected: " + lockName);
187 }
188 if (hcode != syncs[0].getIdentityHashCode()) {
189 throw new RuntimeException("LockInfo: " + syncs[0] +
190 " IdentityHashCode not matched. Expected: " + hcode);
191 }
192
193 }
194 }
195}