Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/javax/management/monitor/GaugeMonitorDeadlockTest.java
38838 views
/*1* Copyright (c) 2005, 2006, 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* @library /lib/testlibrary30* @run clean GaugeMonitorDeadlockTest31* @run build GaugeMonitorDeadlockTest32* @run main GaugeMonitorDeadlockTest 133* @run main GaugeMonitorDeadlockTest 234* @run main GaugeMonitorDeadlockTest 335* @run main GaugeMonitorDeadlockTest 436*/3738import java.lang.management.ManagementFactory;39import java.lang.management.ThreadInfo;40import java.lang.management.ThreadMXBean;41import java.util.concurrent.atomic.AtomicInteger;42import javax.management.JMX;43import javax.management.MBeanServer;44import javax.management.Notification;45import javax.management.NotificationListener;46import javax.management.ObjectName;47import javax.management.monitor.GaugeMonitor;48import javax.management.monitor.GaugeMonitorMBean;4950import jdk.testlibrary.Utils;5152public class GaugeMonitorDeadlockTest {53private static enum When {IN_GET_ATTRIBUTE, IN_NOTIFY};54private static long checkingTime;5556public static void main(String[] args) throws Exception {57if (args.length != 1)58throw new Exception("Arg should be test number");59checkingTime = Utils.adjustTimeout(1000); // default 1s timeout60System.out.println("=== checkingTime = " + checkingTime + "ms");6162int testNo = Integer.parseInt(args[0]) - 1;63TestCase test = testCases[testNo];64System.out.println("Test: " + test.getDescription());65test.run();66System.out.println("Test passed");67}6869private static abstract class TestCase {70TestCase(String description, When when) {71this.description = description;72this.when = when;73}7475void run() throws Exception {76final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();77final ObjectName observedName = new ObjectName("a:b=c");78final ObjectName monitorName = new ObjectName("a:type=Monitor");79mbs.registerMBean(new GaugeMonitor(), monitorName);80final GaugeMonitorMBean monitorProxy =81JMX.newMBeanProxy(mbs, monitorName, GaugeMonitorMBean.class);82final TestMBean observedProxy =83JMX.newMBeanProxy(mbs, observedName, TestMBean.class);8485final Runnable sensitiveThing = new Runnable() {86public void run() {87doSensitiveThing(monitorProxy, observedName);88}89};9091final Runnable nothing = new Runnable() {92public void run() {}93};9495final Runnable withinGetAttribute =96(when == When.IN_GET_ATTRIBUTE) ? sensitiveThing : nothing;9798mbs.registerMBean(new Test(withinGetAttribute), observedName);99monitorProxy.addObservedObject(observedName);100monitorProxy.setObservedAttribute("Thing");101monitorProxy.setThresholds(105, 100);102monitorProxy.setGranularityPeriod(10L); // 10 ms103monitorProxy.setNotifyHigh(true);104monitorProxy.setNotifyLow(true);105106System.out.println("=== Waiting observedProxy.getGetCount() to be "107+ "changed, presumable deadlock if timeout?");108final int initGetCount = observedProxy.getGetCount();109monitorProxy.start();110111long checkedTime = System.currentTimeMillis();112long nowTime;113ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();114while (observedProxy.getGetCount() == initGetCount) {115Thread.sleep(100);116117nowTime = System.currentTimeMillis();118if (nowTime - checkedTime >= checkingTime) {119System.out.println("=== Checking deadlocked ...");120if (threadMXBean.findDeadlockedThreads() != null) {121for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {122System.out.println(info);123}124throw new Error("Found deadlocked threads: "125+ threadMXBean.findDeadlockedThreads().length);126}127checkedTime = System.currentTimeMillis();128}129}130131// This won't show up as a deadlock in CTRL-\ or in132// ThreadMXBean.findDeadlockedThreads(), because they don't133// see that thread A is waiting for thread B (B.join()), and134// thread B is waiting for a lock held by thread A135136// Now we know the monitor has observed the initial value,137// so if we want to test notify behaviour we can trigger by138// exceeding the threshold.139if (when == When.IN_NOTIFY) {140final Thread testedThread = new Thread(sensitiveThing);141final AtomicInteger notifCount = new AtomicInteger();142final NotificationListener listener = new NotificationListener() {143public void handleNotification(Notification n, Object h) {144testedThread.start();145try {146testedThread.join();147} catch (InterruptedException e) {148throw new RuntimeException(e);149}150notifCount.incrementAndGet();151}152};153mbs.addNotificationListener(monitorName, listener, null, null);154observedProxy.setThing(1000);155System.out.println("=== Waiting notifications, presumable "156+ "deadlock if timeout?");157long startTime = System.currentTimeMillis();158checkedTime = startTime;159while (notifCount.get() == 0) {160Thread.sleep(100);161162nowTime = System.currentTimeMillis();163if (nowTime - checkedTime >= checkingTime) {164System.out.println("=== Checking the thread state ...");165if (testedThread.isAlive()) {166System.out.println("=== Waiting testedThread to die "167+ "after " + (nowTime - startTime) + "ms");168169ThreadInfo tinfo = threadMXBean.getThreadInfo(testedThread.getId());170if (Thread.State.BLOCKED.equals(tinfo.getThreadState())) {171for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {172System.out.println(info);173}174} else {175System.out.println(tinfo);176}177} else {178System.out.println("=== The testedThread is dead as wished, "179+ "the test must be passed soon.");180}181checkedTime = System.currentTimeMillis();182}183}184}185}186187abstract void doSensitiveThing(GaugeMonitorMBean monitorProxy,188ObjectName observedName);189190String getDescription() {191return description;192}193194private final String description;195private final When when;196}197198private static final TestCase[] testCases = {199new TestCase("Remove monitored MBean within monitored getAttribute",200When.IN_GET_ATTRIBUTE) {201@Override202void doSensitiveThing(GaugeMonitorMBean monitorProxy,203ObjectName observedName) {204monitorProxy.removeObservedObject(observedName);205}206},207new TestCase("Stop monitor within monitored getAttribute",208When.IN_GET_ATTRIBUTE) {209@Override210void doSensitiveThing(GaugeMonitorMBean monitorProxy,211ObjectName observedName) {212monitorProxy.stop();213}214},215new TestCase("Remove monitored MBean within threshold listener",216When.IN_NOTIFY) {217@Override218void doSensitiveThing(GaugeMonitorMBean monitorProxy,219ObjectName observedName) {220monitorProxy.removeObservedObject(observedName);221}222},223new TestCase("Stop monitor within threshold listener",224When.IN_NOTIFY) {225@Override226void doSensitiveThing(GaugeMonitorMBean monitorProxy,227ObjectName observedName) {228monitorProxy.stop();229}230},231};232233public static interface TestMBean {234public int getThing();235public void setThing(int thing);236public int getGetCount();237}238239public static class Test implements TestMBean {240public Test(Runnable runWithinGetAttribute) {241this.runWithinGetAttribute = runWithinGetAttribute;242}243244public int getThing() {245Thread t = new Thread(runWithinGetAttribute);246t.start();247try {248t.join();249} catch (InterruptedException e) {250throw new RuntimeException(e);251}252getCount++;253return thing;254}255256public void setThing(int thing) {257this.thing = thing;258}259260public int getGetCount() {261return getCount;262}263264private final Runnable runWithinGetAttribute;265private volatile int getCount;266private volatile int thing;267}268}269270271