/*
 * Copyright (c) 1998, 2008, 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 4116437
 * @summary Distributed Garbage Collector Memory Leak
 *
 * @author Laird Dornin
 *
 * @library ../../testlibrary
 * @build CheckLeaseLeak CheckLeaseLeak_Stub LeaseLeakClient LeaseLeak
 * @run main/othervm/timeout=240 CheckLeaseLeak
 *
 */

/**
 * A bug in sun.rmi.transport.DGCImp.checkLeases() results in memory
 * leak of LeaseInfo objects.
 *
 * In order to verify that this problem no longer exists, we create a
 * remote object and a serveral clients in different VMs. The clients
 * call a remote method on an exported object. This will cause the rmi
 * runtime to create several references (all with different vmids) to
 * the remote object.  Each vmid needs a seperate LeaseInfo object in
 * the object table target DGCImpl.leaseTable.  If the leak is fixed,
 * the leaseTable field will contain no objects.  We use reflection to
 * find the number of objects contained in this table.
 */

import java.rmi.*;
import java.rmi.server.*;
import sun.rmi.transport.*;
import sun.rmi.*;
import java.util.Map;
import java.io.*;
import java.lang.reflect.*;
import java.rmi.registry.*;

public class CheckLeaseLeak extends UnicastRemoteObject implements LeaseLeak {

    public CheckLeaseLeak() throws RemoteException { }
    public void ping () throws RemoteException { }

    /**
     * Id to fake the DGC_ID, so we can later get a reference to the
     * DGCImpl in the object table.
     */
    private final static int DGC_ID = 2;

    private final static int ITERATIONS = 10;
    private final static int numberPingCalls = 0;
    private final static int CHECK_INTERVAL = 400;
    private final static int LEASE_VALUE = 20;

    public static void main (String[] args) {
        CheckLeaseLeak leakServer = null;
        int numLeft =0;

        /*
         * we want DGC to collect leases *quickly*
         * decrease the lease check interval
         */
        TestLibrary.setInteger("sun.rmi.dgc.checkInterval",
                               CHECK_INTERVAL);
        TestLibrary.setInteger("java.rmi.dgc.leaseValue",
                               LEASE_VALUE);

        try {
            Registry registry =
                java.rmi.registry.LocateRegistry.
                    createRegistry(TestLibrary.REGISTRY_PORT);

            leakServer = new CheckLeaseLeak();
            registry.rebind("/LeaseLeak", leakServer);

            /* create a bunch of clients in a *different* vm */
            for (int i = 0 ; i < ITERATIONS ; i ++ ) {
                System.err.println("Created client: " + i);

                JavaVM jvm = new JavaVM("LeaseLeakClient",
                                        " -Djava.security.policy=" +
                                        TestParams.defaultPolicy, "");
                jvm.start();

                if (jvm.getVM().waitFor() == 1 ) {
                    TestLibrary.bomb("Client process failed");
                }
            }
            numLeft = getDGCLeaseTableSize();
            Thread.sleep(3000);

        } catch(Exception e) {
            TestLibrary.bomb("CheckLeaseLeak Error: ", e);
        } finally {
            if (leakServer != null) {
                TestLibrary.unexport(leakServer);
                leakServer = null;
            }
        }

        /* numLeft should be 2 - if 11 there is a problem. */
        if (numLeft > 2) {
            TestLibrary.bomb("Too many objects in DGCImpl.leaseTable: "+
                            numLeft);
        } else {
            System.err.println("Check leaseInfo leak passed with " +
                               numLeft
                                   + " object(s) in the leaseTable");
        }
    }

    /**
     * Obtain a reference to the main DGCImpl via reflection.  Extract
     * the DGCImpl using the ObjectTable and the well known ID of the
     * DGCImpl.
     */
    private static int getDGCLeaseTableSize () {
        int numLeaseInfosLeft = 0;

        /**
         * Will eventually be set to point at the leaseTable inside
         * DGCImpl.
         */
        Map leaseTable = null;
        final Remote[] dgcImpl = new Remote[1];
        Field f;

        try {
            f = (Field) java.security.AccessController.doPrivileged
                (new java.security.PrivilegedExceptionAction() {
                    public Object run() throws Exception {

                        ObjID dgcID = new ObjID(DGC_ID);

                        /*
                         * Construct an ObjectEndpoint containing DGC's
                         * ObjID.
                         */
                        Class oeClass =
                            Class.forName("sun.rmi.transport.ObjectEndpoint");
                        Class[] constrParams =
                            new Class[]{ ObjID.class, Transport.class };
                        Constructor oeConstructor =
                            oeClass.getDeclaredConstructor(constrParams);
                        oeConstructor.setAccessible(true);
                        Object oe =
                            oeConstructor.newInstance(
                                new Object[]{ dgcID, null });

                        /*
                         * Get Target that contains DGCImpl in ObjectTable
                         */
                        Class objTableClass =
                            Class.forName("sun.rmi.transport.ObjectTable");
                        Class getTargetParams[] = new Class[] { oeClass };
                        Method objTableGetTarget =
                            objTableClass.getDeclaredMethod("getTarget",
                                                            getTargetParams);
                        objTableGetTarget.setAccessible(true);
                        Target dgcTarget = (Target)
                            objTableGetTarget.invoke(null, new Object[]{ oe });

                        /* get the DGCImpl from its Target */
                        Method targetGetImpl =
                            dgcTarget.getClass().getDeclaredMethod
                            ("getImpl", null);
                        targetGetImpl.setAccessible(true);
                        dgcImpl[0] =
                            (Remote) targetGetImpl.invoke(dgcTarget, null);

                        /* Get the lease table from the DGCImpl. */
                        Field reflectedLeaseTable =
                            dgcImpl[0].getClass().getDeclaredField
                            ("leaseTable");
                        reflectedLeaseTable.setAccessible(true);

                        return reflectedLeaseTable;
                    }
            });

            /**
             * This is the leaseTable that will fill up with LeaseInfo
             * objects if the LeaseInfo memory leak is not fixed.
             */
            leaseTable = (Map) f.get(dgcImpl[0]);

            numLeaseInfosLeft = leaseTable.size();

        } catch(Exception e) {
            if (e instanceof java.security.PrivilegedActionException)
                e = ((java.security.PrivilegedActionException) e).
                    getException();
            TestLibrary.bomb(e);
        }

        return numLeaseInfosLeft;
    }
}
