Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/javax/management/remote/mandatory/connection/MultiThreadDeadLockTest.java
38867 views
/*1* Copyright (c) 2008, 2013, 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*/222324import java.io.IOException;25import java.io.Serializable;26import java.net.Socket;27import java.rmi.server.RMIClientSocketFactory;28import java.util.HashMap;29import javax.management.MBeanServer;30import javax.management.MBeanServerFactory;31import javax.management.Notification;32import javax.management.NotificationBroadcasterSupport;33import javax.management.NotificationListener;34import javax.management.ObjectName;35import javax.management.remote.JMXConnector;36import javax.management.remote.JMXConnectorFactory;37import javax.management.remote.JMXConnectorServer;38import javax.management.remote.JMXConnectorServerFactory;39import javax.management.remote.JMXServiceURL;40import javax.management.remote.rmi.RMIConnectorServer;4142/*43* @test44* @bug 669718045* @summary test on a client notification deadlock.46* @author Shanliang JIANG47* @run clean MultiThreadDeadLockTest48* @run build MultiThreadDeadLockTest49* @run main MultiThreadDeadLockTest50*/5152public class MultiThreadDeadLockTest {5354private static long serverTimeout = 500L;5556public static void main(String[] args) throws Exception {57print("Create the MBean server");58MBeanServer mbs = MBeanServerFactory.createMBeanServer();5960print("Initialize environment map");61HashMap env = new HashMap();6263print("Specify a client socket factory to control socket creation.");64env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE,65clientFactory);6667print("Specify a server idle timeout to make a server close an idle connection.");68env.put("jmx.remote.x.server.connection.timeout", serverTimeout);6970print("Disable client heartbeat.");71env.put("jmx.remote.x.client.connection.check.period", 0);7273env.put("jmx.remote.x.notification.fetch.timeout", serverTimeout);7475print("Create an RMI server");76JMXServiceURL url = new JMXServiceURL("rmi", null, 0);77JMXConnectorServer server =78JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);79server.start();8081url = server.getAddress();8283print("Create jmx client on "+url);84StateMachine.setState(CREATE_SOCKET); // allow to create client socket85client = JMXConnectorFactory.connect(url, env);86Thread.sleep(100);8788totoName = new ObjectName("default:name=toto");89mbs.registerMBean(toto, totoName);90print("Register the mbean: " + totoName);9192print("Add listener to toto MBean");93client.getMBeanServerConnection().addNotificationListener(94totoName, myListener, null, null);95Thread.sleep(10);9697print("send notif, listener will block the fetcher");98toto.sendNotif();99Thread.sleep(100);100101StateMachine.setState(NO_OP);102103print("Sleep 3 times of server idle timeout: "+serverTimeout+104", the sever should close the idle connection.");105Thread.sleep(serverTimeout*3);106107print("start the user thread to call mbean method, it will get IOexception" +108" and start the reconnection, the socket factory will block the" +109" socket creation.");110UserThread ut = new UserThread();111ut.start();112Thread.sleep(10);113114print("Free the listener, the fetcher will get IO and makes " +115"a deadlock if the bug is not fixed.");116StateMachine.setState(FREE_LISTENER);117Thread.sleep(100);118119print("Allow to create new socket for the reconnection");120StateMachine.setState(CREATE_SOCKET);121122print("Check whether the user thread gets free to call the mbean.");123if (!ut.waitDone(5000)) {124throw new RuntimeException("Possible deadlock!");125}126127print("Remove the listener.");128client.getMBeanServerConnection().removeNotificationListener(129totoName, myListener, null, null);130Thread.sleep(serverTimeout*3);131132print("\nWell passed, bye!");133134client.close();135Thread.sleep(10);136server.stop();137}138139private static ObjectName totoName = null;140private static JMXConnector client;141142public static class UserThread extends Thread {143public UserThread() {144setDaemon(true);145}146147public void run() {148try {149client.getMBeanServerConnection().invoke(150totoName, "allowReturn", null, null);151} catch (Exception e) {152throw new Error(e);153}154155synchronized(UserThread.class) {156done = true;157UserThread.class.notify();158}159}160161public boolean waitDone(long timeout) {162synchronized(UserThread.class) {163if(!done) {164try {165UserThread.class.wait(timeout);166} catch (Exception e) {167throw new Error(e);168}169}170}171return done;172}173174private boolean done = false;175}176177public static interface TotoMBean {178public void allowReturn();179}180181public static class Toto extends NotificationBroadcasterSupport182implements TotoMBean {183184public void allowReturn() {185enter("allowReturn");186187leave("allowReturn");188}189190public void sendNotif() {191enter("sendNotif");192193sendNotification(new Notification("Toto", totoName, 0));194195leave("sendNotif");196}197}198private static Toto toto = new Toto();199200public static NotificationListener myListener = new NotificationListener() {201public void handleNotification(Notification notification, Object handback) {202enter("handleNotification");203204StateMachine.waitState(FREE_LISTENER);205206leave("handleNotification");207}208};209210public static class RMIClientFactory211implements RMIClientSocketFactory, Serializable {212213public Socket createSocket(String host, int port) throws IOException {214enter("createSocket");215//print("Calling createSocket(" + host + " " + port + ")");216217StateMachine.waitState(CREATE_SOCKET);218Socket s = new Socket(host, port);219leave("createSocket");220221return s;222}223}224private static RMIClientFactory clientFactory = new RMIClientFactory();225226private static int CREATE_SOCKET = 1;227private static int FREE_LISTENER = 3;228private static int NO_OP = 0;229230public static class StateMachine {231232private static int state = NO_OP;233private static int[] lock = new int[0];234235public static void waitState(int s) {236synchronized (lock) {237while (state != s) {238try {239lock.wait();240} catch (InterruptedException ire) {241// should not242throw new Error(ire);243}244}245}246}247248public static int getState() {249synchronized (lock) {250return state;251}252}253254public static void setState(int s) {255synchronized (lock) {256state = s;257lock.notifyAll();258}259}260}261262private static void print(String m) {263System.out.println(m);264}265266private static void enter(String m) {267System.out.println("\n---Enter the method " + m);268}269270private static void leave(String m) {271System.out.println("===Leave the method: " + m);272}273}274275276