1 /*
2 * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /* @test
25 * @bug 4017232
26 * @summary If, after returning a reference to a remote object in the current
27 * VM (which gets implicitly converted to a remote stub), the client fails to
28 * both send a DGC dirty call and to send a "DGC acknowledgment", the RMI
29 * runtime should eventually allow the remote object to be garbage collected,
30 * rather than pinning it indefinitely.
31 * @author Peter Jones
32 *
33 * @build DGCAckFailure DGCAckFailure_Stub
34 * @run main/othervm DGCAckFailure
35 */
36
37 import java.io.*;
38 import java.net.*;
39 import java.lang.ref.*;
40
41 import java.rmi.*;
42 import java.rmi.server.*;
43
44 interface ReturnRemote extends Remote {
45 Object returnRemote() throws RemoteException;
46 }
47
48 public class DGCAckFailure implements ReturnRemote {
49
50 private static final long TIMEOUT = 20000;
51
52 public Object returnRemote() {
53 return new Wrapper(this);
54 }
55
56 public static void main(String[] args) throws Exception {
57
58 System.setProperty("sun.rmi.dgc.ackTimeout", "10000");
59
60 /*
61 * Set a socket factory that has a hook for shutting down all client
62 * output (writes from client-created sockets and new connection
63 * attempts). We then use this hook right before a remote stub gets
64 * deserialized, so that the client will not be able to send a DGC
65 * dirty call, or a DGC acknowledgment. Without the DGC ack, we
66 * hope that the RMI runtime will still eventually allow the remote
67 * object to be garbage collected.
68 */
69 RMISocketFactory.setSocketFactory(new TestSF());
70 System.err.println("test socket factory set");
71
72 Remote impl = new DGCAckFailure();
73 ReferenceQueue refQueue = new ReferenceQueue();
74 Reference weakRef = new WeakReference(impl, refQueue);
75 ReturnRemote stub =
76 (ReturnRemote) UnicastRemoteObject.exportObject(impl);
77 System.err.println("remote object exported; stub = " + stub);
78
79 try {
80 Object wrappedStub = stub.returnRemote();
81 System.err.println("invocation returned: " + wrappedStub);
82
83 impl = null;
84 stub = null; // in case 4114579 ever gets fixed
85 System.err.println("strong references to impl cleared");
86
87 System.err.println("waiting for weak reference notification:");
88 Reference ref = null;
89 for (int i = 0; i < 6; i++) {
90 System.gc();
91 ref = refQueue.remove(TIMEOUT / 5);
92 if (ref != null) {
93 break;
94 }
95 }
96 if (ref == weakRef) {
97 System.err.println("TEST PASSED");
98 } else {
99 throw new RuntimeException("TEST FAILED: " +
100 "timed out, remote object not garbage collected");
101 }
102 } finally {
103 try {
104 UnicastRemoteObject.unexportObject((Remote) weakRef.get(),
105 true);
106 } catch (Exception e) {
107 }
108 }
109 }
110
111 private static class Wrapper implements Serializable {
112 private final Remote obj;
113 Wrapper(Remote obj) { this.obj = obj; }
114
115 private void readObject(ObjectInputStream in)
116 throws IOException, ClassNotFoundException
117 {
118 TestSF.shutdownClientOutput();
119 System.err.println(
120 "Wrapper.readObject: SHUTTING DOWN CLIENT OUTPUT");
121 in.defaultReadObject();
|
1 /*
2 * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /* @test
25 * @bug 4017232 8046339
26 * @summary If, after returning a reference to a remote object in the current
27 * VM (which gets implicitly converted to a remote stub), the client fails to
28 * both send a DGC dirty call and to send a "DGC acknowledgment", the RMI
29 * runtime should eventually allow the remote object to be garbage collected,
30 * rather than pinning it indefinitely.
31 * @author Peter Jones
32 *
33 * @build DGCAckFailure DGCAckFailure_Stub
34 * @run main/othervm DGCAckFailure
35 */
36
37 import java.io.*;
38 import java.net.*;
39 import java.lang.reflect.Field;
40 import java.lang.ref.*;
41
42 import java.rmi.*;
43 import java.rmi.server.*;
44 import java.util.Map;
45
46 import sun.rmi.transport.DGCAckHandler;
47
48 interface ReturnRemote extends Remote {
49 Object returnRemote() throws RemoteException;
50 }
51
52 public class DGCAckFailure implements ReturnRemote {
53
54 private static final long TIMEOUT = 20000;
55 private static final long ACK_TIMEOUT = TIMEOUT / 2;
56
57 public Object returnRemote() {
58 return new Wrapper(this);
59 }
60
61 public static void main(String[] args) throws Exception {
62
63 System.setProperty("sun.rmi.dgc.ackTimeout",
64 Long.toString(ACK_TIMEOUT));
65
66 /*
67 * Set a socket factory that has a hook for shutting down all client
68 * output (writes from client-created sockets and new connection
69 * attempts). We then use this hook right before a remote stub gets
70 * deserialized, so that the client will not be able to send a DGC
71 * dirty call, or a DGC acknowledgment. Without the DGC ack, we
72 * hope that the RMI runtime will still eventually allow the remote
73 * object to be garbage collected.
74 */
75 RMISocketFactory.setSocketFactory(new TestSF());
76 System.err.println("test socket factory set");
77
78 Remote impl = new DGCAckFailure();
79 ReferenceQueue refQueue = new ReferenceQueue();
80 Reference weakRef = new WeakReference(impl, refQueue);
81 ReturnRemote stub =
82 (ReturnRemote) UnicastRemoteObject.exportObject(impl);
83 System.err.println("remote object exported; stub = " + stub);
84
85 try {
86 Object wrappedStub = stub.returnRemote();
87 System.err.println("invocation returned: " + wrappedStub);
88
89 impl = null;
90 stub = null; // in case 4114579 ever gets fixed
91 System.err.println("strong references to impl cleared");
92
93 System.err.println("waiting for weak reference notification:");
94 Reference ref = null;
95 for (int i = 0; i < 6; i++) {
96 System.gc();
97 ref = refQueue.remove(TIMEOUT / 5);
98 if (ref != null) {
99 break;
100 }
101 }
102 if (ref != weakRef) {
103 throw new RuntimeException("TEST FAILED: " +
104 "timed out, remote object not garbage collected");
105 }
106
107 // 8046339
108 // All DGCAckHandlers must be properly released after timeout
109 Thread.sleep(ACK_TIMEOUT + 100);
110 try {
111 Field field =
112 DGCAckHandler.class.getDeclaredField("idTable");
113 field.setAccessible(true);
114 Object obj = field.get(null);
115 Map<?,?> idTable = (Map<?,?>)obj;
116
117 if (!idTable.isEmpty()) {
118 throw new RuntimeException("TEST FAILED: " +
119 "DGCAckHandler.idTable isn't empty");
120 }
121 } catch (ReflectiveOperationException roe) {
122 throw new RuntimeException(roe);
123 }
124
125 System.err.println("TEST PASSED");
126
127 } finally {
128 try {
129 UnicastRemoteObject.unexportObject((Remote) weakRef.get(),
130 true);
131 } catch (Exception e) {
132 }
133 }
134 }
135
136 private static class Wrapper implements Serializable {
137 private final Remote obj;
138 Wrapper(Remote obj) { this.obj = obj; }
139
140 private void readObject(ObjectInputStream in)
141 throws IOException, ClassNotFoundException
142 {
143 TestSF.shutdownClientOutput();
144 System.err.println(
145 "Wrapper.readObject: SHUTTING DOWN CLIENT OUTPUT");
146 in.defaultReadObject();
|