File: UnreferencedContext.java

package info (click to toggle)
openjdk-11 11.0.4%2B11-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 757,028 kB
  • sloc: java: 5,016,041; xml: 1,191,974; cpp: 934,731; ansic: 555,697; sh: 24,299; objc: 12,703; python: 3,602; asm: 3,415; makefile: 2,772; awk: 351; sed: 172; perl: 114; jsp: 24; csh: 3
file content (190 lines) | stat: -rw-r--r-- 7,659 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/*
 * Copyright (c) 1998, 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
 * 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
 * @modules java.rmi/sun.rmi.registry
 *          java.rmi/sun.rmi.server
 *          java.rmi/sun.rmi.transport
 *          java.rmi/sun.rmi.transport.tcp
 * @build TestLibrary UnreferencedContext_Stub
 * @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.createRegistryOnEphemeralPort();
            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) {
            }
        }
    }
}