Path: blob/master/test/jdk/javax/management/monitor/CounterMonitorDeadlockTest.java
41152 views
/*1* Copyright (c) 2005, 2015, 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 630318726* @summary Test that no locks are held when a monitor attribute is sampled27* or notif delivered.28* @author Eamonn McManus29*30* @run clean CounterMonitorDeadlockTest31* @run build CounterMonitorDeadlockTest32* @run main CounterMonitorDeadlockTest 133* @run main CounterMonitorDeadlockTest 234* @run main CounterMonitorDeadlockTest 335* @run main CounterMonitorDeadlockTest 436*/3738import java.lang.management.ManagementFactory;39import java.util.concurrent.atomic.AtomicInteger;40import javax.management.JMX;41import javax.management.MBeanServer;42import javax.management.Notification;43import javax.management.NotificationListener;44import javax.management.ObjectName;45import javax.management.monitor.CounterMonitor;46import javax.management.monitor.CounterMonitorMBean;4748public class CounterMonitorDeadlockTest {4950public static void main(String[] args) throws Exception {51if (args.length != 1)52throw new Exception("Arg should be test number");53int testNo = Integer.parseInt(args[0]) - 1;54TestCase test = testCases[testNo];55System.out.println("Test: " + test.getDescription());56test.run();57System.out.println("Test passed");58}5960private static enum When {IN_GET_ATTRIBUTE, IN_NOTIFY};6162private static abstract class TestCase {63TestCase(String description, When when) {64this.description = description;65this.when = when;66}6768void run() throws Exception {69final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();70final ObjectName observedName = new ObjectName("a:b=c");71final ObjectName monitorName = new ObjectName("a:type=Monitor");72mbs.registerMBean(new CounterMonitor(), monitorName);73final CounterMonitorMBean monitorProxy =74JMX.newMBeanProxy(mbs, monitorName, CounterMonitorMBean.class);75final TestMBean observedProxy =76JMX.newMBeanProxy(mbs, observedName, TestMBean.class);7778final Runnable sensitiveThing = new Runnable() {79public void run() {80doSensitiveThing(monitorProxy, observedName);81}82};8384final Runnable nothing = new Runnable() {85public void run() {}86};8788final Runnable withinGetAttribute =89(when == When.IN_GET_ATTRIBUTE) ? sensitiveThing : nothing;9091mbs.registerMBean(new Test(withinGetAttribute), observedName);92monitorProxy.addObservedObject(observedName);93monitorProxy.setObservedAttribute("Thing");94monitorProxy.setInitThreshold(100);95monitorProxy.setGranularityPeriod(10L); // 10 ms96monitorProxy.setNotify(true);9798final int initGetCount = observedProxy.getGetCount();99monitorProxy.start();100101System.out.println("Checking GetCount, possible deadlock if timeout.");102do { // 8038322. Until timeout of testing harness103Thread.sleep(200);104} while ((observedProxy.getGetCount()) == initGetCount);105System.out.println("Done!");106107// This won't show up as a deadlock in CTRL-\ or in108// ThreadMXBean.findDeadlockedThreads(), because they don't109// see that thread A is waiting for thread B (B.join()), and110// thread B is waiting for a lock held by thread A111112// Now we know the monitor has observed the initial value,113// so if we want to test notify behaviour we can trigger by114// exceeding the threshold.115if (when == When.IN_NOTIFY) {116final AtomicInteger notifCount = new AtomicInteger();117final NotificationListener listener = new NotificationListener() {118public void handleNotification(Notification n, Object h) {119Thread t = new Thread(sensitiveThing);120t.start();121try {122t.join();123} catch (InterruptedException e) {124throw new RuntimeException(e);125}126notifCount.incrementAndGet();127}128};129mbs.addNotificationListener(monitorName, listener, null, null);130observedProxy.setThing(1000);131System.out.println("Waiting notifCount.get() != 0, possible deadlock if timeout.");132do {133Thread.sleep(200);134} while(notifCount.get() == 0); // 8038322. Until timeout of testing harness135System.out.println("Done");136}137138}139140abstract void doSensitiveThing(CounterMonitorMBean monitorProxy,141ObjectName observedName);142143String getDescription() {144return description;145}146147private final String description;148private final When when;149}150151private static final TestCase[] testCases = {152new TestCase("Remove monitored MBean within monitored getAttribute",153When.IN_GET_ATTRIBUTE) {154@Override155void doSensitiveThing(CounterMonitorMBean monitorProxy,156ObjectName observedName) {157monitorProxy.removeObservedObject(observedName);158}159},160new TestCase("Stop monitor within monitored getAttribute",161When.IN_GET_ATTRIBUTE) {162@Override163void doSensitiveThing(CounterMonitorMBean monitorProxy,164ObjectName observedName) {165monitorProxy.stop();166}167},168new TestCase("Remove monitored MBean within threshold listener",169When.IN_NOTIFY) {170@Override171void doSensitiveThing(CounterMonitorMBean monitorProxy,172ObjectName observedName) {173monitorProxy.removeObservedObject(observedName);174}175},176new TestCase("Stop monitor within threshold listener",177When.IN_NOTIFY) {178@Override179void doSensitiveThing(CounterMonitorMBean monitorProxy,180ObjectName observedName) {181monitorProxy.stop();182}183},184};185186public static interface TestMBean {187public int getThing();188public void setThing(int thing);189public int getGetCount();190}191192public static class Test implements TestMBean {193public Test(Runnable runWithinGetAttribute) {194this.runWithinGetAttribute = runWithinGetAttribute;195}196197public int getThing() {198Thread t = new Thread(runWithinGetAttribute);199t.start();200try {201t.join();202} catch (InterruptedException e) {203throw new RuntimeException(e);204}205getCount++;206return thing;207}208209public void setThing(int thing) {210this.thing = thing;211}212213public int getGetCount() {214return getCount;215}216217private final Runnable runWithinGetAttribute;218private volatile int getCount;219private volatile int thing;220}221}222223224