MyOwnSynchronizer.java revision 9330:8b1f1c2a400f
1/*
2 * Copyright (c) 2005, 2013, 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     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/othervm 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}
196