view test/java/rmi/server/Unreferenced/unreferencedContext/UnreferencedContext.java @ 4943:649b424bb842

7142596: RMI JPRT tests are failing Summary: Changed RMI tests to use random port numbers for the RMI Registry and RMID so the tests can be run concurrently without test failures due to tests using the same port numbers. Reviewed-by: smarks, alanb Contributed-by: olivier.lagneau@oracle.com
author andrew
date Wed, 12 Jun 2013 11:48:21 +0100
parents 00cd9dc3c2b5
children
line wrap: on
line source

/*
 * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/* @test
 * @bug 4171278
 * @summary A remote object's unreferenced() method should be invoked with the
 * context class loader set to the same context class loader that would be set
 * when remote calls for that object are being executed: the object's class's
 * class loader, or the context class loader set when the remote object was
 * exported, if it is a child of the remote object's class loader.
 * @author Peter Jones
 *
 * @bug 4214123
 * @summary Unreferenced.unreferenced(...) threads should run in the nonSystem group.
 *          To complete the fix for, 4182104, RMI unreferenced threads should also
 *          run in the nonSystem so that they do not need permissions to modify the
 *          system thread group.
 *
 * @author Laird Dornin
 *
 * @library ../../../testlibrary
 * @build UnreferencedContext
 * @build UnreferencedContext_Stub
 * @build TestLibrary
 * @run main/othervm/timeout=120 UnreferencedContext
 */

import java.net.*;
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;

public class UnreferencedContext implements Remote, Unreferenced, Runnable {

    private final static String BINDING = "UnreferencedContext";
    private final static long GC_INTERVAL = 6000;
    private final static long TIMEOUT = 60000;

    private Object lock = new Object();
    private boolean unreferencedInvoked = false;
    private ClassLoader unreferencedContext;

    public void run() {
        System.err.println("unreferenced method created thread succesfully");
    }

    public void unreferenced() {
        // turn on security to ensure that the action below will not
        // require extra permissions
        System.setSecurityManager(new java.rmi.RMISecurityManager());

        // exercise functionality prohibited by 4214123
        (new Thread(this)).start();

        System.err.println("unreferenced() method invoked");
        synchronized (lock) {
            unreferencedInvoked = true;
            unreferencedContext =
                Thread.currentThread().getContextClassLoader();
            lock.notify();
        }
    }

    public static void main(String[] args) {

        System.err.println("\nRegression test for bug 4171278\n");

        /*
         * Set the interval that RMI will request for GC latency (before RMI
         * gets initialized and this property is read) to an unrealistically
         * small value, so that this test shouldn't have to wait too long.
         */
        System.setProperty("sun.rmi.dgc.client.gcInterval",
            String.valueOf(GC_INTERVAL));

        UnreferencedContext obj = new UnreferencedContext();

        try {
            /*
             * This little trick is necessary to make sure that the RMI server
             * threads for objects created on the default port get created
             * before we set our special context class loader, so that they
             * don't *accidentally* inherit it when making the unreferenced()
             * callback.
             */
            UnicastRemoteObject.exportObject(obj);
            UnicastRemoteObject.unexportObject(obj, true);

            /*
             * Now create special context class loader before exporting the
             * remote object for real, so that it should be set when the
             * object's unreferenced() method is called.
             */
            ClassLoader intendedContext = new URLClassLoader(new URL[0]);
            Thread.currentThread().setContextClassLoader(intendedContext);
            System.err.println(
                "created and set intended context class loader: " +
                intendedContext);

            UnicastRemoteObject.exportObject(obj);
            System.err.println("exported remote object");

            Registry registry1 = TestLibrary.createRegistryOnUnusedPort();
            int port = TestLibrary.getRegistryPort(registry1);
            System.err.println("created registry");

            Registry registry = LocateRegistry.getRegistry("", port);
            registry.bind(BINDING, obj);
            System.err.println("bound remote object in registry");

            synchronized (obj.lock) {
                registry.unbind(BINDING);
                System.err.println("unbound remote object from registry; " +
                    "waiting for unreferenced() callback...");
                /*
                 * This incantation seems sufficient to work around the
                 * ramifications of 4164696, so that this test will actually
                 * prove something useful about 1.2Beta4 or 1.2FCS before
                 * 4171278 was fixed.
                 */
                for (int i = 0; i < 10; i++) {
                    System.gc();
                    obj.lock.wait(TIMEOUT / 10);
                    if (obj.unreferencedInvoked) {
                        break;
                    }
                }

                if (obj.unreferencedInvoked) {
                    System.err.println(
                        "invoked with context class loader: " +
                        obj.unreferencedContext);

                    if (obj.unreferencedContext == intendedContext) {
                        System.err.println(
                            "TEST PASSED: unreferenced() invoked" +
                            " with intended context class loader");
                    } else {
                        throw new RuntimeException(
                            "TEST FAILED: unreferenced() invoked" +
                            " with incorrect context class loader");
                    }
                } else {
                    throw new RuntimeException(
                        "TEST FAILED: unreferenced() not invoked after " +
                        ((double) TIMEOUT / 1000.0) + " seconds or unreferenced failed to create a thread");
                }
            }

        } catch (Exception e) {
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            } else {
                throw new RuntimeException(
                    "TEST FAILED: unexpected exception: " + e.toString());
            }
        } finally {
            /*
             * When all is said and done, try to unexport the remote object
             * so that the VM has a chance to exit.
             */
            try {
                UnicastRemoteObject.unexportObject(obj, true);
            } catch (RemoteException e) {
            }
        }
    }
}