Path: blob/master/test/jdk/javax/management/monitor/StringMonitorDeadlockTest.java
41149 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* @key intermittent27* @summary Test that no locks are held when a monitor attribute is sampled28* or notif delivered.29* @author Eamonn McManus30*31* @run clean StringMonitorDeadlockTest32* @run build StringMonitorDeadlockTest33* @run main StringMonitorDeadlockTest 134* @run main StringMonitorDeadlockTest 235* @run main StringMonitorDeadlockTest 336* @run main StringMonitorDeadlockTest 437*/3839import java.lang.management.ManagementFactory;40import java.util.concurrent.atomic.AtomicInteger;41import javax.management.JMX;42import javax.management.MBeanServer;43import javax.management.Notification;44import javax.management.NotificationListener;45import javax.management.ObjectName;46import javax.management.monitor.StringMonitor;47import javax.management.monitor.StringMonitorMBean;4849public class StringMonitorDeadlockTest {5051public static void main(String[] args) throws Exception {52if (args.length != 1)53throw new Exception("Arg should be test number");54int testNo = Integer.parseInt(args[0]) - 1;55TestCase test = testCases[testNo];56System.out.println("Test: " + test.getDescription());57test.run();58System.out.println("Test passed");59}6061private static enum When {IN_GET_ATTRIBUTE, IN_NOTIFY};6263private static abstract class TestCase {64TestCase(String description, When when) {65this.description = description;66this.when = when;67}6869void run() throws Exception {70final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();71final ObjectName observedName = new ObjectName("a:b=c");72final ObjectName monitorName = new ObjectName("a:type=Monitor");73mbs.registerMBean(new StringMonitor(), monitorName);74final StringMonitorMBean monitorProxy =75JMX.newMBeanProxy(mbs, monitorName, StringMonitorMBean.class);76final TestMBean observedProxy =77JMX.newMBeanProxy(mbs, observedName, TestMBean.class);7879final Runnable sensitiveThing = new Runnable() {80public void run() {81doSensitiveThing(monitorProxy, observedName);82}83};8485final Runnable nothing = new Runnable() {86public void run() {}87};8889final Runnable withinGetAttribute =90(when == When.IN_GET_ATTRIBUTE) ? sensitiveThing : nothing;9192mbs.registerMBean(new Test(withinGetAttribute), observedName);93monitorProxy.addObservedObject(observedName);94monitorProxy.setObservedAttribute("Thing");95monitorProxy.setStringToCompare("old");96monitorProxy.setGranularityPeriod(10L); // 10 ms97monitorProxy.setNotifyDiffer(true);9899final int initGetCount = observedProxy.getGetCount();100monitorProxy.start();101102int getCount = initGetCount;103for (int i = 0; i < 500; i++) { // 500 * 10 = 5 seconds104getCount = observedProxy.getGetCount();105if (getCount != initGetCount)106break;107Thread.sleep(10);108}109if (getCount <= initGetCount)110throw new Exception("Test failed: presumable deadlock");111// This won't show up as a deadlock in CTRL-\ or in112// ThreadMXBean.findDeadlockedThreads(), because they don't113// see that thread A is waiting for thread B (B.join()), and114// thread B is waiting for a lock held by thread A115116// Now we know the monitor has observed the initial value,117// so if we want to test notify behaviour we can trigger by118// exceeding the threshold.119if (when == When.IN_NOTIFY) {120final AtomicInteger notifCount = new AtomicInteger();121final NotificationListener listener = new NotificationListener() {122public void handleNotification(Notification n, Object h) {123Thread t = new Thread(sensitiveThing);124t.start();125try {126t.join();127} catch (InterruptedException e) {128throw new RuntimeException(e);129}130notifCount.incrementAndGet();131}132};133mbs.addNotificationListener(monitorName, listener, null, null);134observedProxy.setThing("new");135for (int i = 0; i < 500 && notifCount.get() == 0; i++)136Thread.sleep(10);137if (notifCount.get() == 0)138throw new Exception("Test failed: presumable deadlock");139}140141}142143abstract void doSensitiveThing(StringMonitorMBean monitorProxy,144ObjectName observedName);145146String getDescription() {147return description;148}149150private final String description;151private final When when;152}153154private static final TestCase[] testCases = {155new TestCase("Remove monitored MBean within monitored getAttribute",156When.IN_GET_ATTRIBUTE) {157@Override158void doSensitiveThing(StringMonitorMBean monitorProxy,159ObjectName observedName) {160monitorProxy.removeObservedObject(observedName);161}162},163new TestCase("Stop monitor within monitored getAttribute",164When.IN_GET_ATTRIBUTE) {165@Override166void doSensitiveThing(StringMonitorMBean monitorProxy,167ObjectName observedName) {168monitorProxy.stop();169}170},171new TestCase("Remove monitored MBean within threshold listener",172When.IN_NOTIFY) {173@Override174void doSensitiveThing(StringMonitorMBean monitorProxy,175ObjectName observedName) {176monitorProxy.removeObservedObject(observedName);177}178},179new TestCase("Stop monitor within threshold listener",180When.IN_NOTIFY) {181@Override182void doSensitiveThing(StringMonitorMBean monitorProxy,183ObjectName observedName) {184monitorProxy.stop();185}186},187};188189public static interface TestMBean {190public String getThing();191public void setThing(String thing);192public int getGetCount();193}194195public static class Test implements TestMBean {196public Test(Runnable runWithinGetAttribute) {197this.runWithinGetAttribute = runWithinGetAttribute;198}199200public String getThing() {201Thread t = new Thread(runWithinGetAttribute);202t.start();203try {204t.join();205} catch (InterruptedException e) {206throw new RuntimeException(e);207}208getCount++;209return thing;210}211212public void setThing(String thing) {213this.thing = thing;214}215216public int getGetCount() {217return getCount;218}219220private final Runnable runWithinGetAttribute;221private volatile int getCount;222private volatile String thing;223}224}225226227