Path: blob/master/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java
41155 views
/*1* Copyright (c) 1998, 2017, 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/* @test24* @bug 411643725* @summary Distributed Garbage Collector Memory Leak26*27* @author Laird Dornin28*29* @library ../../testlibrary30* @modules java.rmi/sun.rmi.registry31* java.rmi/sun.rmi.server32* java.rmi/sun.rmi.transport:open33* java.rmi/sun.rmi.transport34* java.rmi/sun.rmi.transport.tcp35* @build TestLibrary CheckLeaseLeak_Stub LeaseLeakClient LeaseLeak36* @run main/othervm/timeout=240 CheckLeaseLeak37*38*/3940/**41* A bug in sun.rmi.transport.DGCImp.checkLeases() results in memory42* leak of LeaseInfo objects.43*44* In order to verify that this problem no longer exists, we create a45* remote object and a serveral clients in different VMs. The clients46* call a remote method on an exported object. This will cause the rmi47* runtime to create several references (all with different vmids) to48* the remote object. Each vmid needs a seperate LeaseInfo object in49* the object table target DGCImpl.leaseTable. If the leak is fixed,50* the leaseTable field will contain no objects. We use reflection to51* find the number of objects contained in this table.52*/5354import java.rmi.*;55import java.rmi.server.*;56import sun.rmi.transport.*;57import sun.rmi.*;58import java.util.Map;59import java.io.*;60import java.lang.reflect.*;61import java.rmi.registry.*;6263public class CheckLeaseLeak extends UnicastRemoteObject implements LeaseLeak {64public CheckLeaseLeak() throws RemoteException { }65public void ping () throws RemoteException { }6667/**68* Id to fake the DGC_ID, so we can later get a reference to the69* DGCImpl in the object table.70*/71private final static int DGC_ID = 2;7273private final static int ITERATIONS = 10;74private final static int numberPingCalls = 0;75private final static int CHECK_INTERVAL = 400;76private final static int LEASE_VALUE = 20;7778public static void main (String[] args) {79CheckLeaseLeak leakServer = null;80int numLeft =0;8182/*83* we want DGC to collect leases *quickly*84* decrease the lease check interval85*/86TestLibrary.setInteger("sun.rmi.dgc.checkInterval",87CHECK_INTERVAL);88TestLibrary.setInteger("java.rmi.dgc.leaseValue",89LEASE_VALUE);9091try {92Registry registry =93TestLibrary.createRegistryOnEphemeralPort();94int registryPort = TestLibrary.getRegistryPort(registry);9596leakServer = new CheckLeaseLeak();97registry.rebind("/LeaseLeak", leakServer);9899/* create a bunch of clients in a *different* vm */100for (int i = 0 ; i < ITERATIONS ; i ++ ) {101System.err.println("Created client: " + i);102103JavaVM jvm = new JavaVM("LeaseLeakClient",104" -Djava.security.policy=" +105TestParams.defaultPolicy +106" -Drmi.registry.port=" +107registryPort,108"");109110try {111if (jvm.execute() != 0) {112TestLibrary.bomb("Client process failed");113}114} finally {115jvm.destroy();116}117}118numLeft = getDGCLeaseTableSize();119Thread.sleep(3000);120121} catch(Exception e) {122TestLibrary.bomb("CheckLeaseLeak Error: ", e);123} finally {124if (leakServer != null) {125TestLibrary.unexport(leakServer);126leakServer = null;127}128}129130/* numLeft should be 2 - if 11 there is a problem. */131if (numLeft > 2) {132TestLibrary.bomb("Too many objects in DGCImpl.leaseTable: "+133numLeft);134} else {135System.err.println("Check leaseInfo leak passed with " +136numLeft137+ " object(s) in the leaseTable");138}139}140141/**142* Obtain a reference to the main DGCImpl via reflection. Extract143* the DGCImpl using the ObjectTable and the well known ID of the144* DGCImpl.145*/146private static int getDGCLeaseTableSize () {147int numLeaseInfosLeft = 0;148149/**150* Will eventually be set to point at the leaseTable inside151* DGCImpl.152*/153Map leaseTable = null;154final Remote[] dgcImpl = new Remote[1];155Field f;156157try {158f = (Field) java.security.AccessController.doPrivileged159(new java.security.PrivilegedExceptionAction() {160public Object run() throws Exception {161162ObjID dgcID = new ObjID(DGC_ID);163164/*165* Construct an ObjectEndpoint containing DGC's166* ObjID.167*/168Class oeClass =169Class.forName("sun.rmi.transport.ObjectEndpoint");170Class[] constrParams =171new Class[]{ ObjID.class, Transport.class };172Constructor oeConstructor =173oeClass.getDeclaredConstructor(constrParams);174oeConstructor.setAccessible(true);175Object oe =176oeConstructor.newInstance(177new Object[]{ dgcID, null });178179/*180* Get Target that contains DGCImpl in ObjectTable181*/182Class objTableClass =183Class.forName("sun.rmi.transport.ObjectTable");184Class getTargetParams[] = new Class[] { oeClass };185Method objTableGetTarget =186objTableClass.getDeclaredMethod("getTarget",187getTargetParams);188objTableGetTarget.setAccessible(true);189Target dgcTarget = (Target)190objTableGetTarget.invoke(null, new Object[]{ oe });191192/* get the DGCImpl from its Target */193Method targetGetImpl =194dgcTarget.getClass().getDeclaredMethod195("getImpl", null);196targetGetImpl.setAccessible(true);197dgcImpl[0] =198(Remote) targetGetImpl.invoke(dgcTarget, null);199200/* Get the lease table from the DGCImpl. */201Field reflectedLeaseTable =202dgcImpl[0].getClass().getDeclaredField203("leaseTable");204reflectedLeaseTable.setAccessible(true);205206return reflectedLeaseTable;207}208});209210/**211* This is the leaseTable that will fill up with LeaseInfo212* objects if the LeaseInfo memory leak is not fixed.213*/214leaseTable = (Map) f.get(dgcImpl[0]);215216numLeaseInfosLeft = leaseTable.size();217218} catch(Exception e) {219if (e instanceof java.security.PrivilegedActionException)220e = ((java.security.PrivilegedActionException) e).221getException();222TestLibrary.bomb(e);223}224225return numLeaseInfosLeft;226}227}228229230