changeset 11425:fa8729272b5b

8046339: sun.rmi.transport.DGCAckHandler leaks memory Reviewed-by: smarks
author igerasim
date Wed, 10 Feb 2016 18:32:53 +0300
parents d6641d6e093c
children 103329a57527
files src/share/classes/sun/rmi/transport/DGCAckHandler.java test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java
diffstat 2 files changed, 35 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/sun/rmi/transport/DGCAckHandler.java	Fri Feb 05 13:53:39 2016 +0000
+++ b/src/share/classes/sun/rmi/transport/DGCAckHandler.java	Wed Feb 10 18:32:53 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -118,6 +118,9 @@
         if (objList != null && task == null) {
             task = scheduler.schedule(new Runnable() {
                 public void run() {
+                    if (id != null) {
+                        idTable.remove(id);
+                    }
                     release();
                 }
             }, dgcAckTimeout, TimeUnit.MILLISECONDS);
--- a/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java	Fri Feb 05 13:53:39 2016 +0000
+++ b/test/java/rmi/dgc/dgcAckFailure/DGCAckFailure.java	Wed Feb 10 18:32:53 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4017232
+ * @bug 4017232 8046339
  * @summary If, after returning a reference to a remote object in the current
  * VM (which gets implicitly converted to a remote stub), the client fails to
  * both send a DGC dirty call and to send a "DGC acknowledgment", the RMI
@@ -36,10 +36,14 @@
 
 import java.io.*;
 import java.net.*;
+import java.lang.reflect.Field;
 import java.lang.ref.*;
 
 import java.rmi.*;
 import java.rmi.server.*;
+import java.util.Map;
+
+import sun.rmi.transport.DGCAckHandler;
 
 interface ReturnRemote extends Remote {
     Object returnRemote() throws RemoteException;
@@ -48,6 +52,7 @@
 public class DGCAckFailure implements ReturnRemote {
 
     private static final long TIMEOUT = 20000;
+    private static final long ACK_TIMEOUT = TIMEOUT / 2;
 
     public Object returnRemote() {
         return new Wrapper(this);
@@ -55,7 +60,8 @@
 
     public static void main(String[] args) throws Exception {
 
-        System.setProperty("sun.rmi.dgc.ackTimeout", "10000");
+        System.setProperty("sun.rmi.dgc.ackTimeout",
+                Long.toString(ACK_TIMEOUT));
 
         /*
          * Set a socket factory that has a hook for shutting down all client
@@ -93,12 +99,31 @@
                     break;
                 }
             }
-            if (ref == weakRef) {
-                System.err.println("TEST PASSED");
-            } else {
+            if (ref != weakRef) {
                 throw new RuntimeException("TEST FAILED: " +
                     "timed out, remote object not garbage collected");
             }
+
+            // 8046339
+            // All DGCAckHandlers must be properly released after timeout
+            Thread.sleep(ACK_TIMEOUT + 100);
+            try {
+                Field field =
+                        DGCAckHandler.class.getDeclaredField("idTable");
+                field.setAccessible(true);
+                Object obj = field.get(null);
+                Map<?,?> idTable = (Map<?,?>)obj;
+
+                if (!idTable.isEmpty()) {
+                    throw new RuntimeException("TEST FAILED: " +
+                            "DGCAckHandler.idTable isn't empty");
+                }
+            } catch (ReflectiveOperationException roe) {
+                throw new RuntimeException(roe);
+            }
+
+            System.err.println("TEST PASSED");
+
         } finally {
             try {
                 UnicastRemoteObject.unexportObject((Remote) weakRef.get(),