169N/A/*
5266N/A * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A */
0N/A
0N/Aimport java.rmi.*;
0N/Aimport sun.rmi.transport.*;
0N/Aimport sun.rmi.*;
0N/Aimport java.io.*;
0N/Aimport java.lang.reflect.*;
0N/Aimport java.rmi.dgc.*;
0N/Aimport java.util.*;
0N/Aimport java.rmi.registry.*;
0N/Aimport java.rmi.server.*;
0N/A
169N/Apublic class TestImpl extends UnicastRemoteObject
0N/A implements Test {
0N/A static Thread locker = null;
0N/A static TestImpl foo = null;
0N/A static TestImpl bar = null;
0N/A
0N/A TestImpl() throws RemoteException {
0N/A }
0N/A
0N/A public String echo(String msg) throws RemoteException {
0N/A
169N/A if (locker == null) {
169N/A // hold the target if not already held
169N/A locker = lockTargetExpireLeases(foo, DGCDeadLock.HOLD_TARGET_TIME);
169N/A }
0N/A return "Message received: " + msg;
0N/A }
0N/A
0N/A static public void main(String[] args) {
169N/A Registry registry = null;
0N/A
0N/A try {
5266N/A int registryPort = Integer.parseInt(System.getProperty("rmi.registry.port"));
169N/A registry = java.rmi.registry.LocateRegistry.
5266N/A createRegistry(registryPort);
0N/A
169N/A //export "Foo"
169N/A foo = new TestImpl();
169N/A Naming.rebind("rmi://:" +
5266N/A registryPort
169N/A + "/Foo", foo);
0N/A
169N/A try {
169N/A //export "Bar" after leases have been expired.
169N/A bar = new TestImpl();
169N/A Naming.rebind("rmi://localhost:" +
5266N/A registryPort
169N/A + "/Bar", bar);
169N/A } catch (Exception e) {
169N/A throw new RemoteException(e.getMessage());
169N/A }
169N/A Thread.sleep(DGCDeadLock.TEST_FAIL_TIME);
169N/A System.err.println("object vm exiting...");
169N/A System.exit(0);
0N/A
0N/A } catch (Exception e) {
169N/A System.err.println(e.getMessage());
169N/A e.printStackTrace();
0N/A } finally {
169N/A TestLibrary.unexport(registry);
169N/A registry = null;
169N/A }
0N/A }
0N/A
0N/A static Thread lockTargetExpireLeases(Remote toLock, int timeOut) {
169N/A Thread t = new Thread((Runnable) new TargetLocker(toLock, timeOut));
169N/A t.start();
169N/A return t;
0N/A }
0N/A
0N/A static class TargetLocker implements Runnable {
0N/A
169N/A Remote toLock = null;
169N/A int timeOut = 0;
0N/A
169N/A TargetLocker(Remote toLock, int timeOut) {
169N/A this.toLock = toLock;
169N/A this.timeOut = timeOut;
169N/A }
0N/A
169N/A public void run() {
169N/A try {
169N/A // give dgc dirty calls time to finish.
169N/A Thread.currentThread().sleep(4000);
0N/A
169N/A java.security.AccessController.
169N/A doPrivileged(new LockTargetCheckLeases(toLock,
169N/A timeOut));
0N/A
169N/A } catch (Exception e) {
169N/A System.err.println(e.getMessage());
169N/A e.printStackTrace();
169N/A System.exit(1);
169N/A }
169N/A }
0N/A }
0N/A
169N/A static class LockTargetCheckLeases
169N/A implements java.security.PrivilegedAction {
169N/A
169N/A Remote toLock = null;
169N/A int timeOut = 0;
0N/A
169N/A LockTargetCheckLeases(Remote toLock, int timeOut) {
169N/A this.toLock = toLock;
169N/A this.timeOut = timeOut;
169N/A }
0N/A
169N/A public Object run() {
169N/A try {
169N/A
169N/A Class args[] = new Class[1];
169N/A
169N/A Class objTableClass = Class.forName
169N/A ("sun.rmi.transport.ObjectTable");
0N/A
169N/A /* get the Target that corresponds to toLock from the
169N/A * ObjectTable
169N/A */
169N/A args[0] = Class.forName("java.rmi.Remote");
169N/A Method objTableGetTarget =
169N/A objTableClass.getDeclaredMethod("getTarget", args );
169N/A objTableGetTarget.setAccessible(true);
169N/A
169N/A Target lockTarget =
169N/A ((Target) objTableGetTarget.invoke
169N/A (null , new Object [] {toLock} ));
169N/A
169N/A // make sure the lease on this object has expired.
169N/A expireLeases(lockTarget);
0N/A
169N/A // stop other threads from using the target for toLock.
169N/A synchronized (lockTarget) {
169N/A System.err.println("Locked the relevant target, sleeping " +
169N/A timeOut/1000 + " seconds");
169N/A Thread.currentThread().sleep(timeOut);
169N/A System.err.println("Target unlocked");
169N/A }
169N/A
169N/A } catch (Exception e) {
169N/A System.err.println(e.getMessage());
169N/A e.printStackTrace();
169N/A System.exit(1);
169N/A }
169N/A return null;
169N/A }
0N/A }
0N/A
0N/A /* leases have long values, so no dirty calls which would lock out
0N/A * a clean call, but the leases need to expire anyway, so we do it
169N/A * explicitly.
0N/A */
0N/A static void expireLeases(Target t) throws Exception {
0N/A
169N/A final Target target = t;
169N/A
169N/A java.security.AccessController.doPrivileged(
0N/A
169N/A // put this into another class?
169N/A new java.security.PrivilegedAction() {
169N/A public Object run() {
169N/A try {
169N/A
169N/A Class DGCClass = Class.forName("sun.rmi.transport.DGCImpl");
169N/A Method getDGCImpl =
169N/A DGCClass.getDeclaredMethod("getDGCImpl", null );
169N/A getDGCImpl.setAccessible(true);
0N/A
169N/A // make sure the lease on this object has expired.
169N/A DGC dgcImpl = ((DGC) getDGCImpl.invoke(null, null));
169N/A
169N/A /* Get the lease table from the DGCImpl. */
169N/A Field reflectedLeaseTable =
169N/A dgcImpl.getClass().getDeclaredField("leaseTable");
169N/A reflectedLeaseTable.setAccessible(true);
169N/A
169N/A Map leaseTable = (Map) reflectedLeaseTable.get(dgcImpl);
169N/A
169N/A // dont really need this synchronization...
169N/A synchronized (leaseTable) {
169N/A Iterator en = leaseTable.values().iterator();
169N/A while (en.hasNext()) {
169N/A Object info = en.next();
0N/A
169N/A /* Get the notifySet in the leaseInfo object. */
169N/A Field notifySetField =
169N/A info.getClass().getDeclaredField("notifySet");
169N/A notifySetField.setAccessible(true);
169N/A HashSet notifySet = (HashSet) notifySetField.get(info);
169N/A
169N/A Iterator iter = notifySet.iterator();
169N/A while (iter.hasNext()) {
169N/A Target notified = (Target) iter.next();
169N/A
169N/A if (notified == target) {
169N/A
169N/A /* Get and set the expiration field from the info object. */
169N/A Field expirationField = info.getClass().
169N/A getDeclaredField("expiration");
169N/A expirationField.setAccessible(true);
169N/A expirationField.setLong(info, 0);
169N/A }
169N/A }
169N/A }
169N/A }
169N/A } catch (Exception e) {
169N/A System.err.println(e.getMessage());
169N/A e.printStackTrace();
169N/A System.exit(1);
169N/A }
169N/A // no interesting return value for this privileged action
169N/A return null;
169N/A }
169N/A });
0N/A }
0N/A}