Path: blob/master/test/jdk/java/lang/management/ManagementFactory/ThreadMXBeanProxy.java
41152 views
/*1* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 5086470 6358247 7193302 804821526* @summary Test type conversion when invoking ThreadMXBean.dumpAllThreads27* through proxy.28* @author Mandy Chung29*30* @run main ThreadMXBeanProxy31*/3233import static java.lang.management.ManagementFactory.*;34import java.lang.management.*;35import java.util.*;36import java.util.concurrent.locks.*;37import java.util.concurrent.TimeUnit;38import java.io.*;39import javax.management.*;4041public class ThreadMXBeanProxy {42private static MBeanServer server =43ManagementFactory.getPlatformMBeanServer();44private static ThreadMXBean mbean;45static Mutex mutex = new Mutex();46static Object lock = new Object();47static Object waiter = new Object();48static MyThread thread = new MyThread();49public static void main(String[] argv) throws Exception {50mbean = newPlatformMXBeanProxy(server,51THREAD_MXBEAN_NAME,52ThreadMXBean.class);5354if (!mbean.isSynchronizerUsageSupported()) {55System.out.println("Monitoring of synchronizer usage not supported");56return;57}5859thread.setDaemon(true);60thread.start();6162// wait until myThread acquires mutex and lock owner is set.63while (!(mutex.isLocked() && mutex.getLockOwner() == thread)) {64try {65Thread.sleep(100);66} catch (InterruptedException e) {67throw new RuntimeException(e);68}69}7071// 'thread' holds the mutex, which means it must also have the monitor of72// 'waiter' at least until it does the wait(). So we acquire the monitor of73// 'waiter' here, which ensures that 'thread' must be in wait()74synchronized(waiter) {75}7677long[] ids = new long[] { thread.getId() };7879// validate the local access80ThreadInfo[] infos = getThreadMXBean().getThreadInfo(ids, true, true);81if (infos.length != 1) {82throw new RuntimeException("Returned ThreadInfo[] of length=" +83infos.length + ". Expected to be 1.");84}85thread.checkThreadInfo(infos[0]);8687// validate the remote access88infos = mbean.getThreadInfo(ids, true, true);89if (infos.length != 1) {90throw new RuntimeException("Returned ThreadInfo[] of length=" +91infos.length + ". Expected to be 1.");92}93thread.checkThreadInfo(infos[0]);9495boolean found = false;96infos = mbean.dumpAllThreads(true, true);97for (ThreadInfo ti : infos) {98if (ti.getThreadId() == thread.getId()) {99thread.checkThreadInfo(ti);100found = true;101}102}103104if (!found) {105throw new RuntimeException("No ThreadInfo found for MyThread");106}107108System.out.println("Test passed");109}110111static class MyThread extends Thread {112public MyThread() {113super("MyThread");114}115public void run() {116synchronized (lock) {117synchronized(waiter) {118mutex.lock();119try {120waiter.wait();121} catch (InterruptedException e) {122throw new RuntimeException(e);123}124}125}126}127128int OWNED_MONITORS = 1;129int OWNED_SYNCS = 1;130void checkThreadInfo(ThreadInfo info) {131if (!getName().equals(info.getThreadName())) {132throw new RuntimeException("Name: " + info.getThreadName() +133" not matched. Expected: " + getName());134}135136MonitorInfo[] monitors = info.getLockedMonitors();137if (monitors.length != OWNED_MONITORS) {138throw new RuntimeException("Number of locked monitors = " +139monitors.length +140" not matched. Expected: " + OWNED_MONITORS);141}142MonitorInfo m = monitors[0];143StackTraceElement ste = m.getLockedStackFrame();144int depth = m.getLockedStackDepth();145StackTraceElement[] stacktrace = info.getStackTrace();146if (!ste.equals(stacktrace[depth])) {147System.out.println("LockedStackFrame:- " + ste);148System.out.println("StackTrace at " + depth + " :-" +149stacktrace[depth]);150throw new RuntimeException("LockedStackFrame does not match " +151"stack frame in ThreadInfo.getStackTrace");152}153154String className = lock.getClass().getName();155int hcode = System.identityHashCode(lock);156if (!className.equals(m.getClassName()) ||157hcode != m.getIdentityHashCode() ||158!m.getLockedStackFrame().getMethodName().equals("run")) {159System.out.println(info);160throw new RuntimeException("MonitorInfo " + m +161" doesn't match.");162}163164LockInfo[] syncs = info.getLockedSynchronizers();165if (syncs.length != OWNED_SYNCS) {166throw new RuntimeException("Number of locked syncs = " +167syncs.length + " not matched. Expected: " + OWNED_SYNCS);168}169AbstractOwnableSynchronizer s = mutex.getSync();170String lockName = s.getClass().getName();171hcode = System.identityHashCode(s);172if (!lockName.equals(syncs[0].getClassName())) {173throw new RuntimeException("LockInfo : " + syncs[0] +174" class name not matched. Expected: " + lockName);175}176if (hcode != syncs[0].getIdentityHashCode()) {177throw new RuntimeException("LockInfo: " + syncs[0] +178" IdentityHashCode not matched. Expected: " + hcode);179}180LockInfo li = info.getLockInfo();181if (li == null) {182throw new RuntimeException("Expected non-null LockInfo");183}184}185}186static class Mutex implements Lock, java.io.Serializable {187188// Our internal helper class189class Sync extends AbstractQueuedSynchronizer {190// Report whether in locked state191protected boolean isHeldExclusively() {192return getState() == 1;193}194195// Acquire the lock if state is zero196public boolean tryAcquire(int acquires) {197assert acquires == 1; // Otherwise unused198if (compareAndSetState(0, 1)) {199setExclusiveOwnerThread(Thread.currentThread());200return true;201}202return false;203}204205// Release the lock by setting state to zero206protected boolean tryRelease(int releases) {207assert releases == 1; // Otherwise unused208if (getState() == 0) throw new IllegalMonitorStateException();209setExclusiveOwnerThread(null);210setState(0);211return true;212}213214// Provide a Condition215Condition newCondition() { return new ConditionObject(); }216217// Deserialize properly218private void readObject(ObjectInputStream s)219throws IOException, ClassNotFoundException {220s.defaultReadObject();221setState(0); // reset to unlocked state222}223224protected Thread getLockOwner() {225return getExclusiveOwnerThread();226}227}228229// The sync object does all the hard work. We just forward to it.230private final Sync sync = new Sync();231232public void lock() { sync.acquire(1); }233public boolean tryLock() { return sync.tryAcquire(1); }234public void unlock() { sync.release(1); }235public Condition newCondition() { return sync.newCondition(); }236public boolean isLocked() { return sync.isHeldExclusively(); }237public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }238public void lockInterruptibly() throws InterruptedException {239sync.acquireInterruptibly(1);240}241public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {242return sync.tryAcquireNanos(1, unit.toNanos(timeout));243}244245public Thread getLockOwner() { return sync.getLockOwner(); }246247public AbstractOwnableSynchronizer getSync() { return sync; }248}249}250251252