jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java
author chegar
Thu, 24 Mar 2016 11:56:47 +0000
changeset 36669 17af8b44d311
parent 36511 9d0388c6b336
child 36972 27147cde3256
permissions -rw-r--r--
8152642: Remove sun.misc.Unsafe dependency from java.lang.reflect.Proxy Reviewed-by: alanb, shade
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
21655
55f32ae4f920 8028229: Fix more raw types lint warning in core libraries
darcy
parents: 20825
diff changeset
     2
 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3959
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3959
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3959
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3959
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 3959
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package java.lang.reflect;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.lang.ref.WeakReference;
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
    29
import java.security.AccessController;
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
    30
import java.security.PrivilegedAction;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.util.Arrays;
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    32
import java.util.Collections;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    33
import java.util.Deque;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    34
import java.util.HashMap;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    35
import java.util.HashSet;
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
    36
import java.util.IdentityHashMap;
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    37
import java.util.LinkedList;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    38
import java.util.List;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import java.util.Map;
17497
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
    40
import java.util.Objects;
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    41
import java.util.Set;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    42
import java.util.WeakHashMap;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    43
import java.util.concurrent.atomic.AtomicInteger;
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
    44
import java.util.concurrent.atomic.AtomicLong;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
    45
import java.util.function.BiFunction;
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    46
import java.util.stream.Collectors;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    47
import java.util.stream.Stream;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    48
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    49
import jdk.internal.loader.BootLoader;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    50
import jdk.internal.module.Modules;
36669
17af8b44d311 8152642: Remove sun.misc.Unsafe dependency from java.lang.reflect.Proxy
chegar
parents: 36511
diff changeset
    51
import jdk.internal.misc.Unsafe;
34882
ce2a8ec851c1 8145544: Move sun.misc.VM to jdk.internal.misc
chegar
parents: 34704
diff changeset
    52
import jdk.internal.misc.VM;
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
    53
import sun.reflect.CallerSensitive;
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
    54
import sun.reflect.Reflection;
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
    55
import sun.reflect.misc.ReflectUtil;
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
    56
import sun.security.util.SecurityConstants;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 *
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    60
 * {@code Proxy} provides static methods for creating objects that act like instances
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    61
 * of interfaces but allow for customized method invocation.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    62
 * To create a proxy instance for some interface {@code Foo}:
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    63
 * <pre>{@code
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 *     InvocationHandler handler = new MyInvocationHandler(...);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    66
 *                                          new Class<?>[] { Foo.class },
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 *                                          handler);
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    68
 * }</pre>
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 *
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    70
 * <p>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    71
 * A <em>proxy class</em> is a class created at runtime that implements a specified
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    72
 * list of interfaces, known as <em>proxy interfaces</em>. A <em>proxy instance</em>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    73
 * is an instance of a proxy class.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 * Each proxy instance has an associated <i>invocation handler</i>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * object, which implements the interface {@link InvocationHandler}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 * A method invocation on a proxy instance through one of its proxy
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 * interfaces will be dispatched to the {@link InvocationHandler#invoke
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 * invoke} method of the instance's invocation handler, passing the proxy
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 * instance, a {@code java.lang.reflect.Method} object identifying
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 * the method that was invoked, and an array of type {@code Object}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 * containing the arguments.  The invocation handler processes the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
 * encoded method invocation as appropriate and the result that it
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
 * returns will be returned as the result of the method invocation on
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
 * the proxy instance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
 * <p>A proxy class has the following properties:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
 * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
 * <li>The unqualified name of a proxy class is unspecified.  The space
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
 * of class names that begin with the string {@code "$Proxy"}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
 * should be, however, reserved for proxy classes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
 *
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    94
 * <li>The package and module in which a proxy class is defined is specified
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    95
 * <a href="#membership">below</a>.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    96
 *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    97
 * <li>A proxy class is <em>final and non-abstract</em>.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
    98
 *
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
 * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
 * <li>A proxy class implements exactly the interfaces specified at its
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   102
 * creation, in the same order. Invoking {@link Class#getInterfaces getInterfaces}
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   103
 * on its {@code Class} object will return an array containing the same
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
 * list of interfaces (in the order specified at its creation), invoking
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   105
 * {@link Class#getMethods getMethods} on its {@code Class} object will return
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
 * an array of {@code Method} objects that include all of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
 * methods in those interfaces, and invoking {@code getMethod} will
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
 * find methods in the proxy interfaces as would be expected.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
 *
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   110
 * <li>The {@link java.security.ProtectionDomain} of a proxy class
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
 * is the same as that of system classes loaded by the bootstrap class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
 * loader, such as {@code java.lang.Object}, because the code for a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
 * proxy class is generated by trusted system code.  This protection
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   114
 * domain will typically be granted {@code java.security.AllPermission}.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
 *
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   116
 * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method can be used
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   117
 * to determine if a given class is a proxy class.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
 * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
 * <p>A proxy instance has the following properties:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
 * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
 * <li>Given a proxy instance {@code proxy} and one of the
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   124
 * interfaces, {@code Foo}, implemented by its proxy class, the
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
 * following expression will return true:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
 * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
 *     {@code proxy instanceof Foo}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
 * </pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
 * and the following cast operation will succeed (rather than throwing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
 * a {@code ClassCastException}):
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
 * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
 *     {@code (Foo) proxy}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
 * </pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
 * <li>Each proxy instance has an associated invocation handler, the one
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
 * that was passed to its constructor.  The static
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
 * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
 * will return the invocation handler associated with the proxy instance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
 * passed as its argument.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
 * <li>An interface method invocation on a proxy instance will be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
 * encoded and dispatched to the invocation handler's {@link
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
 * InvocationHandler#invoke invoke} method as described in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
 * documentation for that method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
 * <li>An invocation of the {@code hashCode},
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
 * {@code equals}, or {@code toString} methods declared in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
 * {@code java.lang.Object} on a proxy instance will be encoded and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
 * dispatched to the invocation handler's {@code invoke} method in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
 * the same manner as interface method invocations are encoded and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
 * dispatched, as described above.  The declaring class of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
 * {@code Method} object passed to {@code invoke} will be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
 * {@code java.lang.Object}.  Other public methods of a proxy
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
 * instance inherited from {@code java.lang.Object} are not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
 * overridden by a proxy class, so invocations of those methods behave
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
 * like they do for instances of {@code java.lang.Object}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
 * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
 *
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   159
 * <h3><a name="membership">Package and Module Membership of Proxy Class</a></h3>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   160
 *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   161
 * The package and module to which a proxy class belongs are chosen such that
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   162
 * the accessibility of the proxy class is in line with the accessibility of
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   163
 * the proxy interfaces. Specifically, the package and the module membership
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   164
 * of a proxy class defined via the
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   165
 * {@link Proxy#getProxyClass(ClassLoader, Class[])} or
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   166
 * {@link Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)}
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   167
 * methods is specified as follows:
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   168
 *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   169
 * <ol>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   170
 * <li>If all the proxy interfaces are in <em>exported</em> packages:
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   171
 * <ol type="a">
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   172
 * <li>if all the proxy interfaces are <em>public</em>, then the proxy class is
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   173
 *     <em>public</em> in a package exported by the
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   174
 *     {@linkplain ClassLoader#getUnnamedModule() unnamed module} of the specified
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   175
 *     loader. The name of the package is unspecified.</li>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   176
 *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   177
 * <li>if at least one of all the proxy interfaces is <em>non-public</em>, then
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   178
 *     the proxy class is <em>non-public</em> in the package and module of the
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   179
 *     non-public interfaces. All the non-public interfaces must be in the same
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   180
 *     package and module; otherwise, proxying them is
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   181
 *     <a href="#restrictions">not possible</a>.</li>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   182
 * </ol>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   183
 * </li>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   184
 * <li>If at least one proxy interface is a <em>non-exported</em> package:
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   185
 * <ol type="a">
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   186
 * <li>if all the proxy interfaces are <em>public</em>, then the proxy class is
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   187
 *     <em>public</em> in a <em>non-exported</em> package of
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   188
 *     <a href="#dynamicmodule"><em>dynamic module</em>.</a>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   189
 *     The names of the package and the module are unspecified.</li>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   190
 *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   191
 * <li>if at least one of all the proxy interfaces is <em>non-public</em>, then
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   192
 *     the proxy class is <em>non-public</em> in the package and module of the
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   193
 *     non-public interfaces. All the non-public interfaces must be in the same
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   194
 *     package and module; otherwise, proxying them is
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   195
 *     <a href="#restrictions">not possible</a>.</li>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   196
 * </ol>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   197
 * </li>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   198
 * </ol>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   199
 *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   200
 * <p>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   201
 * Note that if proxy interfaces with a mix of accessibilities --
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   202
 * exported public, exported non-public, non-exported public, non-exported non-public --
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   203
 * are proxied by the same instance, then the proxy class's accessibility is
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   204
 * governed by the least accessible proxy interface.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   205
 * <p>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   206
 * Note that it is possible for arbitrary code to obtain access to a proxy class
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   207
 * in an exported package with {@link AccessibleObject#setAccessible setAccessible},
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   208
 * whereas a proxy class in a non-exported package is never accessible to
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   209
 * code outside the module of the proxy class.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   210
 *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   211
 * <p>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   212
 * Throughout this specification, a "non-exported package" refers to a package that
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   213
 * is not exported to all modules. Specifically, it refers to a package that
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   214
 * either is not exported at all by its containing module or is exported in a
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   215
 * qualified fashion by its containing module.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   216
 *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   217
 * <h3><a name="dynamicmodule">Dynamic Modules</a></h3>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   218
 * <p>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   219
 * A dynamic module is a named module generated at runtime. A proxy class
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   220
 * defined in a dynamic module is encapsulated and not accessible to any module.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   221
 * Calling {@link Constructor#newInstance(Object...)} on a proxy class in
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   222
 * a dynamic module will throw {@code IllegalAccessException};
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   223
 * {@code Proxy.newProxyInstance} method should be used instead.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   224
 *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   225
 * <p>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   226
 * A dynamic module can read the modules of all of the superinterfaces of a proxy class
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   227
 * and the modules of the types referenced by all public method signatures
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   228
 * of a proxy class.  If a superinterface or a referenced type, say {@code T},
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   229
 * is in a non-exported package, the {@linkplain java.lang.reflect.Module module}
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   230
 * of {@code T} is updated to export the package of {@code T} to the dynamic module.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   231
 *
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
 * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
 *
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   234
 * <p>When two or more proxy interfaces contain a method with
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
 * the same name and parameter signature, the order of the proxy class's
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
 * interfaces becomes significant.  When such a <i>duplicate method</i>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
 * is invoked on a proxy instance, the {@code Method} object passed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
 * to the invocation handler will not necessarily be the one whose
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
 * declaring class is assignable from the reference type of the interface
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
 * that the proxy's method was invoked through.  This limitation exists
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
 * because the corresponding method implementation in the generated proxy
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
 * class cannot determine which interface it was invoked through.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
 * Therefore, when a duplicate method is invoked on a proxy instance,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
 * the {@code Method} object for the method in the foremost interface
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
 * that contains the method (either directly or inherited through a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
 * superinterface) in the proxy class's list of interfaces is passed to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
 * the invocation handler's {@code invoke} method, regardless of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
 * reference type through which the method invocation occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
 * <p>If a proxy interface contains a method with the same name and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
 * parameter signature as the {@code hashCode}, {@code equals},
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
 * or {@code toString} methods of {@code java.lang.Object},
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
 * when such a method is invoked on a proxy instance, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
 * {@code Method} object passed to the invocation handler will have
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
 * {@code java.lang.Object} as its declaring class.  In other words,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
 * the public, non-final methods of {@code java.lang.Object}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
 * logically precede all of the proxy interfaces for the determination of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
 * which {@code Method} object to pass to the invocation handler.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
 * <p>Note also that when a duplicate method is dispatched to an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
 * invocation handler, the {@code invoke} method may only throw
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
 * checked exception types that are assignable to one of the exception
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
 * types in the {@code throws} clause of the method in <i>all</i> of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
 * the proxy interfaces that it can be invoked through.  If the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
 * {@code invoke} method throws a checked exception that is not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
 * assignable to any of the exception types declared by the method in one
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
 * of the proxy interfaces that it can be invoked through, then an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
 * unchecked {@code UndeclaredThrowableException} will be thrown by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
 * the invocation on the proxy instance.  This restriction means that not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
 * all of the exception types returned by invoking
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
 * {@code getExceptionTypes} on the {@code Method} object
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
 * passed to the {@code invoke} method can necessarily be thrown
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
 * successfully by the {@code invoke} method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
 * @author      Peter Jones
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
 * @see         InvocationHandler
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
 * @since       1.3
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
public class Proxy implements java.io.Serializable {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
    private static final long serialVersionUID = -2222568056686623797L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
    /** parameter types of a proxy class constructor */
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   283
    private static final Class<?>[] constructorParams =
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        { InvocationHandler.class };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   286
    /**
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
     * the invocation handler for this proxy instance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
     * @serial
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
    protected InvocationHandler h;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
     * Prohibits instantiation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
    private Proxy() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
     * Constructs a new {@code Proxy} instance from a subclass
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
     * (typically, a dynamic proxy class) with the specified value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
     * for its invocation handler.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
     *
17497
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
   303
     * @param  h the invocation handler for this proxy instance
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
   304
     *
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
   305
     * @throws NullPointerException if the given invocation handler, {@code h},
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
   306
     *         is {@code null}.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
    protected Proxy(InvocationHandler h) {
17497
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
   309
        Objects.requireNonNull(h);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        this.h = h;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
     * Returns the {@code java.lang.Class} object for a proxy class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
     * given a class loader and an array of interfaces.  The proxy class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
     * will be defined by the specified class loader and will implement
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   317
     * all of the supplied interfaces.  If any of the given interfaces
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   318
     * is non-public, the proxy class will be non-public. If a proxy class
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   319
     * for the same permutation of interfaces has already been defined by the
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   320
     * class loader, then the existing proxy class will be returned; otherwise,
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
     * a proxy class for those interfaces will be generated dynamically
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
     * and defined by the class loader.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
     * @param   loader the class loader to define the proxy class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
     * @param   interfaces the list of interfaces for the proxy class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
     *          to implement
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
     * @return  a proxy class that is defined in the specified class loader
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
     *          and that implements the specified interfaces
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   329
     * @throws  IllegalArgumentException if any of the <a href="#restrictions">
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   330
     *          restrictions</a> on the parameters are violated
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   331
     * @throws  SecurityException if a security manager, <em>s</em>, is present
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   332
     *          and any of the following conditions is met:
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   333
     *          <ul>
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   334
     *             <li> the given {@code loader} is {@code null} and
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   335
     *             the caller's class loader is not {@code null} and the
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   336
     *             invocation of {@link SecurityManager#checkPermission
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   337
     *             s.checkPermission} with
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   338
     *             {@code RuntimePermission("getClassLoader")} permission
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   339
     *             denies access.</li>
20825
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
   340
     *             <li> for each proxy interface, {@code intf},
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
   341
     *             the caller's class loader is not the same as or an
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
   342
     *             ancestor of the class loader for {@code intf} and
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   343
     *             invocation of {@link SecurityManager#checkPackageAccess
20825
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
   344
     *             s.checkPackageAccess()} denies access to {@code intf}.</li>
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   345
     *          </ul>
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
     * @throws  NullPointerException if the {@code interfaces} array
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
     *          argument or any of its elements are {@code null}
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   348
     *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   349
     * @deprecated Proxy classes generated in a named module are encapsulated and not
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   350
     *      accessible to code outside its module.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   351
     *      {@link Constructor#newInstance(Object...) Constructor.newInstance} will throw
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   352
     *      {@code IllegalAccessException} when it is called on an inaccessible proxy class.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   353
     *      Use {@link #newProxyInstance(ClassLoader, Class[], InvocationHandler)}
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   354
     *      to create a proxy instance instead.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   355
     *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   356
     * @see <a href="#membership">Package and Module Membership of Proxy Class</a>
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
     */
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   358
    @Deprecated
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   359
    @CallerSensitive
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
    public static Class<?> getProxyClass(ClassLoader loader,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
                                         Class<?>... interfaces)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
        throws IllegalArgumentException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
    {
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   364
        final List<Class<?>> intfs = List.of(interfaces);  // interfaces cloned
25533
95f7f4b0bb93 8035009: Make Proxy representations consistent
mchung
parents: 22581
diff changeset
   365
        final SecurityManager sm = System.getSecurityManager();
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   366
        final Class<?> caller = Reflection.getCallerClass();
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   367
        if (sm != null) {
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   368
            checkProxyAccess(caller, loader, intfs);
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   369
        }
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   370
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   371
        return new ProxyBuilder(loader, intfs).build();
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   372
    }
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   373
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   374
    /*
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   375
     * Check permissions required to create a Proxy class.
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   376
     *
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   377
     * To define a proxy class, it performs the access checks as in
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   378
     * Class.forName (VM will invoke ClassLoader.checkPackageAccess):
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   379
     * 1. "getClassLoader" permission check if loader == null
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   380
     * 2. checkPackageAccess on the interfaces it implements
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   381
     *
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   382
     * To get a constructor and new instance of a proxy class, it performs
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   383
     * the package access check on the interfaces it implements
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   384
     * as in Class.getConstructor.
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   385
     *
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   386
     * If an interface is non-public, the proxy class must be defined by
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   387
     * the defining loader of the interface.  If the caller's class loader
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   388
     * is not the same as the defining loader of the interface, the VM
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   389
     * will throw IllegalAccessError when the generated proxy class is
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   390
     * being defined.
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   391
     */
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   392
    private static void checkProxyAccess(Class<?> caller,
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   393
                                         ClassLoader loader,
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   394
                                         List<Class<?>> interfaces)
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   395
    {
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   396
        SecurityManager sm = System.getSecurityManager();
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   397
        if (sm != null) {
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   398
            ClassLoader ccl = caller.getClassLoader();
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   399
            if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   400
                sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   401
            }
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   402
            ReflectUtil.checkProxyPackageAccess(ccl, interfaces.toArray(EMPTY_CLASS_ARRAY));
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   403
        }
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   404
    }
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   405
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   406
    /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   407
     * a key used for proxy class with 0 implemented interfaces
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   408
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   409
    private static final Object key0 = new Object();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   410
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   411
    /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   412
     * Key1 and Key2 are optimized for the common use of dynamic proxies
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   413
     * that implement 1 or 2 interfaces.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   414
     */
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   416
    /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   417
     * a key used for proxy class with 1 implemented interface
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   418
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   419
    private static final class Key1 extends WeakReference<Class<?>> {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   420
        private final int hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   421
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   422
        Key1(Class<?> intf) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   423
            super(intf);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   424
            this.hash = intf.hashCode();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   425
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   427
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   428
        public int hashCode() {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   429
            return hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   430
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   431
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   432
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   433
        public boolean equals(Object obj) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   434
            Class<?> intf;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   435
            return this == obj ||
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   436
                   obj != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   437
                   obj.getClass() == Key1.class &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   438
                   (intf = get()) != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   439
                   intf == ((Key1) obj).get();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   440
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   441
    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   443
    /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   444
     * a key used for proxy class with 2 implemented interfaces
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   445
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   446
    private static final class Key2 extends WeakReference<Class<?>> {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   447
        private final int hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   448
        private final WeakReference<Class<?>> ref2;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   449
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   450
        Key2(Class<?> intf1, Class<?> intf2) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   451
            super(intf1);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   452
            hash = 31 * intf1.hashCode() + intf2.hashCode();
22581
e868cde95050 8032779: Update code in java.lang to use newer language features
psandoz
parents: 21655
diff changeset
   453
            ref2 = new WeakReference<>(intf2);
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   454
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   455
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   456
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   457
        public int hashCode() {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   458
            return hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   459
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   460
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   461
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   462
        public boolean equals(Object obj) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   463
            Class<?> intf1, intf2;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   464
            return this == obj ||
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   465
                   obj != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   466
                   obj.getClass() == Key2.class &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   467
                   (intf1 = get()) != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   468
                   intf1 == ((Key2) obj).get() &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   469
                   (intf2 = ref2.get()) != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   470
                   intf2 == ((Key2) obj).ref2.get();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   471
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   472
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   473
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   474
    /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   475
     * a key used for proxy class with any number of implemented interfaces
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   476
     * (used here for 3 or more only)
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   477
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   478
    private static final class KeyX {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   479
        private final int hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   480
        private final WeakReference<Class<?>>[] refs;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   481
21655
55f32ae4f920 8028229: Fix more raw types lint warning in core libraries
darcy
parents: 20825
diff changeset
   482
        @SuppressWarnings("unchecked")
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   483
        KeyX(List<Class<?>> interfaces) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   484
            hash = Arrays.hashCode(interfaces.toArray());
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   485
            refs = (WeakReference<Class<?>>[])new WeakReference<?>[interfaces.size()];
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   486
            int i = 0;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   487
            for (Class<?> intf : interfaces) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   488
                refs[i++] = new WeakReference<>(intf);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   492
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   493
        public int hashCode() {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   494
            return hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   495
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   497
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   498
        public boolean equals(Object obj) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   499
            return this == obj ||
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   500
                   obj != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   501
                   obj.getClass() == KeyX.class &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   502
                   equals(refs, ((KeyX) obj).refs);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   505
        private static boolean equals(WeakReference<Class<?>>[] refs1,
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   506
                                      WeakReference<Class<?>>[] refs2) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   507
            if (refs1.length != refs2.length) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   508
                return false;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   509
            }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   510
            for (int i = 0; i < refs1.length; i++) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   511
                Class<?> intf = refs1[i].get();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   512
                if (intf == null || intf != refs2[i].get()) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   513
                    return false;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
                }
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   515
            }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   516
            return true;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   517
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   518
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   519
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   520
    /**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   521
     * A function that maps an array of interfaces to an optimal key where
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   522
     * Class objects representing interfaces are weakly referenced.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   523
     */
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   524
    private static final class KeyFactory<T>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   525
        implements BiFunction<T, List<Class<?>>, Object>
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   526
    {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   527
        @Override
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   528
        public Object apply(T t, List<Class<?>> interfaces) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   529
            switch (interfaces.size()) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   530
                case 1: return new Key1(interfaces.get(0)); // the most frequent
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   531
                case 2: return new Key2(interfaces.get(0), interfaces.get(1));
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   532
                case 0: return key0;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   533
                default: return new KeyX(interfaces);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   534
            }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   535
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   536
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   537
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   538
    /**
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   539
     * A factory function that generates, defines and returns the proxy class
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   540
     * given the ClassLoader and array of interfaces.
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   541
     */
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   542
    private static final class ProxyClassFactory {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   543
        private static final Unsafe UNSAFE = Unsafe.getUnsafe();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   544
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   545
        // prefix for all proxy class names
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   546
        private static final String proxyClassNamePrefix = "$Proxy";
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   547
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   548
        // next number to use for generation of unique proxy class names
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   549
        private static final AtomicLong nextUniqueNumber = new AtomicLong();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   550
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   551
        private static Class<?> defineProxyClass(Module m, List<Class<?>> interfaces) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
            String proxyPkg = null;     // package to define proxy class in
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   553
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
             * Record the package of a non-public proxy interface so that the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
             * proxy class will be defined in the same package.  Verify that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
             * all non-public proxy interfaces are in the same package.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
             */
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   560
            for (Class<?> intf : interfaces) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   561
                int flags = intf.getModifiers();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
                if (!Modifier.isPublic(flags)) {
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   563
                    accessFlags = Modifier.FINAL;  // non-public, final
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   564
                    String pkg = intf.getPackageName();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
                    if (proxyPkg == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
                        proxyPkg = pkg;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
                    } else if (!pkg.equals(proxyPkg)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
                        throw new IllegalArgumentException(
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   569
                                "non-public interfaces from different packages");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   574
            if (proxyPkg == null) {
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   575
                // all proxy interfaces are public
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   576
                proxyPkg = m.isNamed() ? PROXY_PACKAGE_PREFIX + "." + m.getName()
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   577
                                       : PROXY_PACKAGE_PREFIX;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   578
            } else if (proxyPkg.isEmpty() && m.isNamed()) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   579
                throw new IllegalArgumentException(
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   580
                        "Unnamed package cannot be added to " + m);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   581
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   582
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   583
            // add the package to the runtime module if not exists
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   584
            if (m.isNamed()) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   585
                m.addPackage(proxyPkg);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   588
            /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   589
             * Choose a name for the proxy class to generate.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   590
             */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   591
            long num = nextUniqueNumber.getAndIncrement();
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   592
            String proxyName = proxyPkg.isEmpty() ? proxyClassNamePrefix + num
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   593
                                                  : proxyPkg + "." + proxyClassNamePrefix + num;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   594
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   595
            ClassLoader loader = getLoader(m);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   596
            trace(proxyName, m, loader, interfaces);
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   597
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   598
            /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   599
             * Generate the specified proxy class.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   600
             */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   601
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   602
                    proxyName, interfaces.toArray(EMPTY_CLASS_ARRAY), accessFlags);
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   603
            try {
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   604
                return UNSAFE.defineClass(proxyName, proxyClassFile, 0, proxyClassFile.length,
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   605
                                          loader, null);
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   606
            } catch (ClassFormatError e) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
                /*
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   608
                 * A ClassFormatError here means that (barring bugs in the
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   609
                 * proxy class generation code) there was some other
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   610
                 * invalid aspect of the arguments supplied to the proxy
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   611
                 * class creation (such as virtual machine limitations
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   612
                 * exceeded).
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
                 */
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   614
                throw new IllegalArgumentException(e.toString());
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
        }
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   617
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   618
        /**
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   619
         * Test if the given class is a proxy class
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   620
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   621
        static boolean isProxyClass(Class<?> c) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   622
            return proxyCache.containsValue(c);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   623
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   624
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   625
        /**
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   626
         * Returns the proxy class.  It will return the cached proxy class
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   627
         * if exists; otherwise, it will create the proxy class and store in
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   628
         * the cache.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   629
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   630
        static Class<?> get(Module module, List<Class<?>> interfaces) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   631
            return proxyCache.get(module, interfaces);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   632
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   633
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   634
        /**
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   635
         * a cache of proxy classes in the named and unnamed module
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   636
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   637
        private static final WeakCache<Module, List<Class<?>>, Class<?>> proxyCache =
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   638
            new WeakCache<>(new KeyFactory<Module>(),
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   639
                new BiFunction<Module, List<Class<?>>, Class<?>>()  {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   640
                    @Override
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   641
                    public Class<?> apply(Module m, List<Class<?>> interfaces) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   642
                        Objects.requireNonNull(m);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   643
                        return defineProxyClass(m, interfaces);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   644
                    }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   645
            });
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   646
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   647
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   648
        private static boolean isExportedType(Class<?> c) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   649
            String pn = c.getPackageName();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   650
            return Modifier.isPublic(c.getModifiers()) && c.getModule().isExported(pn);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   651
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   652
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   653
        private static boolean isPackagePrivateType(Class<?> c) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   654
            return !Modifier.isPublic(c.getModifiers());
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   655
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   656
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   657
        private static String toDetails(Class<?> c) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   658
            String access = "unknown";
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   659
            if (isExportedType(c)) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   660
                access = "exported";
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   661
            } else if (isPackagePrivateType(c)) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   662
                access = "package-private";
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   663
            } else {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   664
                access = "module-private";
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   665
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   666
            ClassLoader ld = c.getClassLoader();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   667
            return String.format("   %s/%s %s loader %s",
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   668
                    c.getModule().getName(), c.getName(), access, ld);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   669
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   670
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   671
        static void trace(String cn, Module module, ClassLoader loader, List<Class<?>> interfaces) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   672
            if (isDebug()) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   673
                System.out.format("PROXY: %s/%s defined by %s%n", module.getName(), cn, loader);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   674
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   675
            if (isDebug("debug")) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   676
                interfaces.stream()
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   677
                          .forEach(c -> System.out.println(toDetails(c)));
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   678
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   679
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   680
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   681
        private static final String DEBUG =
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   682
            AccessController.doPrivileged(new PrivilegedAction<>() {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   683
                public String run() {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   684
                    return System.getProperty("jdk.proxy.debug", "");
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   685
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   686
            });
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   687
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   688
        private static final boolean isDebug() {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   689
            return !DEBUG.isEmpty();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   690
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   691
        private static final boolean isDebug(String flag) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   692
            return DEBUG.equals(flag);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   693
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
    /**
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   697
     * Builder for a proxy class.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   698
     *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   699
     * If the module is not specified in this ProxyBuilder constructor,
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   700
     * it will map from the given loader and interfaces to the module
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   701
     * in which the proxy class will be defined.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   702
     */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   703
    private static final class ProxyBuilder {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   704
        final ClassLoader loader;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   705
        final List<Class<?>> interfaces;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   706
        final Module module;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   707
        ProxyBuilder(ClassLoader loader, List<Class<?>> interfaces) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   708
            if (!VM.isModuleSystemInited()) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   709
                throw new InternalError("Proxy is not supported until module system is fully initialzed");
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   710
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   711
            if (interfaces.size() > 65535) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   712
                throw new IllegalArgumentException("interface limit exceeded");
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   713
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   714
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   715
            Set<Class<?>> refTypes = referencedTypes(loader, interfaces);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   716
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   717
            // IAE if violates any restrictions specified in newProxyInstance
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   718
            validateProxyInterfaces(loader, interfaces, refTypes);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   719
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   720
            this.loader = loader;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   721
            this.interfaces = interfaces;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   722
            this.module = mapToModule(loader, interfaces, refTypes);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   723
            assert getLoader(module) == loader;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   724
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   725
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   726
        /**
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   727
         * Generate a proxy class.  If the target module does not have any
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   728
         * to any interface types, IllegalAccessError will be thrown by the VM
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   729
         * at defineClass time.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   730
         *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   731
         * Must call the checkProxyAccess method to perform permission checks
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   732
         * before calling this.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   733
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   734
        Class<?> build() {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   735
            return ProxyClassFactory.get(module, interfaces);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   736
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   737
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   738
        /**
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   739
         * Validate the given proxy interfaces and the given referenced types
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   740
         * are visible to the defining loader.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   741
         *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   742
         * @throws IllegalArgumentException if it violates the restrictions specified
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   743
         *         in {@link Proxy#newProxyInstance}
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   744
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   745
        static void validateProxyInterfaces(ClassLoader loader,
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   746
                                            List<Class<?>> interfaces,
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   747
                                            Set<Class<?>> refTypes)
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   748
        {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   749
            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.size());
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   750
            for (Class<?> intf : interfaces) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   751
                /*
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   752
                 * Verify that the class loader resolves the name of this
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   753
                 * interface to the same Class object.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   754
                 */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   755
                ensureVisible(loader, intf);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   756
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   757
                /*
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   758
                 * Verify that the Class object actually represents an
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   759
                 * interface.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   760
                 */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   761
                if (!intf.isInterface()) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   762
                    throw new IllegalArgumentException(intf.getName() + " is not an interface");
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   763
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   764
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   765
                /*
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   766
                 * Verify that this interface is not a duplicate.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   767
                 */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   768
                if (interfaceSet.put(intf, Boolean.TRUE) != null) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   769
                    throw new IllegalArgumentException("repeated interface: " + intf.getName());
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   770
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   771
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   772
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   773
            for (Class<?> type : refTypes) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   774
                ensureVisible(loader, type);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   775
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   776
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   777
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   778
        /*
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   779
         * Returns all types referenced by all public method signatures of
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   780
         * the proxy interfaces
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   781
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   782
        static Set<Class<?>> referencedTypes(ClassLoader loader, List<Class<?>> interfaces) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   783
            return interfaces.stream()
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   784
                 .flatMap(intf -> Stream.of(intf.getMethods())
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   785
                                        .flatMap(m -> methodRefTypes(m))
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   786
                                        .map(ProxyBuilder::getElementType)
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   787
                                        .filter(t -> !t.isPrimitive()))
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   788
                 .collect(Collectors.toSet());
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   789
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   790
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   791
        /*
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   792
         * Extracts all types referenced on a method signature including
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   793
         * its return type, parameter types, and exception types.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   794
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   795
        static Stream<Class<?>> methodRefTypes(Method m) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   796
            return Stream.of(new Class<?>[] { m.getReturnType() },
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   797
                             m.getParameterTypes(),
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   798
                             m.getExceptionTypes())
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   799
                         .flatMap(a -> Stream.of(a));
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   800
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   801
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   802
        /**
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   803
         * Returns the module that the generated proxy class belongs to.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   804
         *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   805
         * If all proxy interfaces are public and in exported packages,
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   806
         * then the proxy class is in unnamed module.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   807
         *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   808
         * If any of proxy interface is package-private, then the proxy class
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   809
         * is in the same module of the package-private interface.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   810
         *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   811
         * If all proxy interfaces are public and at least one in a non-exported
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   812
         * package, then the proxy class is in a dynamic module in a non-exported
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   813
         * package.  Reads edge and qualified exports are added for
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   814
         * dynamic module to access.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   815
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   816
        static Module mapToModule(ClassLoader loader, List<Class<?>> interfaces, Set<Class<?>> refTypes) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   817
            Map<Class<?>, Module> modulePrivateTypes = new HashMap<>();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   818
            Map<Class<?>, Module> packagePrivateTypes = new HashMap<>();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   819
            for (Class<?> intf : interfaces) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   820
                Module m = intf.getModule();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   821
                if (Modifier.isPublic(intf.getModifiers())) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   822
                    // module-private types
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   823
                    if (!m.isExported(intf.getPackageName())) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   824
                        modulePrivateTypes.put(intf, m);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   825
                    }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   826
                } else {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   827
                    packagePrivateTypes.put(intf, m);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   828
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   829
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   830
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   831
            // all proxy interfaces are public and exported, the proxy class is in unnamed module
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   832
            // Such proxy class is accessible to any unnamed module and named module that
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   833
            // can read unnamed module
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   834
            if (packagePrivateTypes.isEmpty() && modulePrivateTypes.isEmpty()) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   835
                return loader != null ? loader.getUnnamedModule() : BootLoader.getUnnamedModule();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   836
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   837
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   838
            if (packagePrivateTypes.size() > 0) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   839
                // all package-private types must be in the same runtime package
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   840
                // i.e. same package name and same module (named or unnamed)
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   841
                //
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   842
                // Configuration will fail if M1 and in M2 defined by the same loader
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   843
                // and both have the same package p (so no need to check class loader)
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   844
                if (packagePrivateTypes.size() > 1 &&
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   845
                        (packagePrivateTypes.keySet().stream()  // more than one package
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   846
                                 .map(Class::getPackageName).distinct().count() > 1 ||
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   847
                         packagePrivateTypes.values().stream()  // or more than one module
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   848
                                 .distinct().count() > 1)) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   849
                    throw new IllegalArgumentException(
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   850
                            "non-public interfaces from different packages");
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   851
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   852
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   853
                // all package-private types are in the same module (named or unnamed)
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   854
                Module target = null;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   855
                for (Module m : packagePrivateTypes.values()) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   856
                    if (getLoader(m) != loader) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   857
                        // the specified loader is not the same class loader of the non-public interface
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   858
                        throw new IllegalArgumentException(
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   859
                                "non-public interface is not defined by the given loader");
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   860
                    }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   861
                    target = m;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   862
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   863
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   864
                // validate if the target module can access all other interfaces
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   865
                for (Class<?> intf : interfaces) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   866
                    Module m = intf.getModule();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   867
                    if (m == target) continue;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   868
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   869
                    if (!target.canRead(m) || !m.isExported(intf.getPackageName(), target)) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   870
                        throw new IllegalArgumentException(target + " can't access " + intf.getName());
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   871
                    }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   872
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   873
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   874
                // return the module of the package-private interface
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   875
                return target;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   876
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   877
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   878
            // all proxy interfaces are public and at least one in a non-exported package
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   879
            // map to dynamic proxy module and add reads edge and qualified exports, if necessary
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   880
            Module target = getDynamicModule(loader);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   881
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   882
            // set up proxy class access to proxy interfaces and superinterfaces
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   883
            Deque<Class<?>> deque = new LinkedList<>(interfaces);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   884
            Set<Class<?>> visited = new HashSet<>();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   885
            while (!deque.isEmpty()) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   886
                Class<?> c = deque.poll();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   887
                if (visited.contains(c)) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   888
                    continue;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   889
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   890
                visited.add(c);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   891
                ensureAccess(target, c);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   892
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   893
                // add all superinterfaces
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   894
                for (Class<?> intf : c.getInterfaces()) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   895
                    deque.add(intf);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   896
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   897
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   898
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   899
            // set up proxy class access to types referenced in the method signature
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   900
            refTypes.stream()
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   901
                    .filter(t -> !visited.contains(t))
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   902
                    .forEach(t -> ensureAccess(target, t));
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   903
            return target;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   904
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   905
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   906
        /*
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   907
         * Ensure the given module can access the given class.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   908
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   909
        static void ensureAccess(Module target, Class<?> c) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   910
            Module m = c.getModule();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   911
            // add read edge and qualified export for the target module to access
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   912
            if (!target.canRead(m)) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   913
                Modules.addReads(target, m);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   914
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   915
            String pn = c.getPackageName();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   916
            if (!m.isExported(pn, target)) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   917
                Modules.addExports(m, pn, target);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   918
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   919
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   920
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   921
        /*
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   922
         * Ensure the given class is visible to the class loader.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   923
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   924
        static void ensureVisible(ClassLoader ld, Class<?> c) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   925
            Class<?> type = null;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   926
            try {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   927
                type = Class.forName(c.getName(), false, ld);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   928
            } catch (ClassNotFoundException e) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   929
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   930
            if (type != c) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   931
                throw new IllegalArgumentException(c.getName() +
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   932
                        " referenced from a method is not visible from class loader");
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   933
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   934
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   935
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   936
        static Class<?> getElementType(Class<?> type) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   937
            Class<?> e = type;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   938
            while (e.isArray()) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   939
                e = e.getComponentType();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   940
            }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   941
            return e;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   942
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   943
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   944
        private static final WeakHashMap<ClassLoader, Module> dynProxyModules = new WeakHashMap<>();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   945
        private static final AtomicInteger counter = new AtomicInteger();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   946
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   947
        /*
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   948
         * Define a dynamic module for the generated proxy classes in a non-exported package
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   949
         * named com.sun.proxy.$MODULE.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   950
         *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   951
         * Each class loader will have one dynamic module.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   952
         */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   953
        static Module getDynamicModule(ClassLoader loader) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   954
            return dynProxyModules.computeIfAbsent(loader, ld -> {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   955
                // create a dynamic module and setup module access
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   956
                String mn = "jdk.proxy" + counter.incrementAndGet();
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   957
                String pn = PROXY_PACKAGE_PREFIX + "." + mn;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   958
                Module m = Modules.defineModule(loader, mn, Collections.singleton(pn));
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   959
                Modules.addReads(m, Proxy.class.getModule());
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   960
                // java.base to create proxy instance
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   961
                Modules.addExports(m, pn, Object.class.getModule());
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   962
                return m;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   963
            });
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   964
        }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   965
    }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   966
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   967
    /**
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   968
     * Returns a proxy instance for the specified interfaces
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
     * that dispatches method invocations to the specified invocation
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   970
     * handler.
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   971
     * <p>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   972
     * <a name="restrictions">{@code IllegalArgumentException} will be thrown
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   973
     * if any of the following restrictions is violated:</a>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   974
     * <ul>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   975
     * <li>All of {@code Class} objects in the given {@code interfaces} array
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   976
     * must represent interfaces, not classes or primitive types.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
     *
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   978
     * <li>No two elements in the {@code interfaces} array may
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   979
     * refer to identical {@code Class} objects.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   980
     *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   981
     * <li>All of the interface types must be visible by name through the
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   982
     * specified class loader. In other words, for class loader
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   983
     * {@code cl} and every interface {@code i}, the following
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   984
     * expression must be true:<p>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   985
     * {@code Class.forName(i.getName(), false, cl) == i}
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   986
     *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   987
     * <li>All of the types referenced by all
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   988
     * public method signatures of the specified interfaces
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   989
     * and those inherited by their superinterfaces
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   990
     * must be visible by name through the specified class loader.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   991
     *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   992
     * <li>All non-public interfaces must be in the same package
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   993
     * and module, defined by the specified class loader and
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   994
     * the module of the non-public interfaces can access all of
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   995
     * the interface types; otherwise, it would not be possible for
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   996
     * the proxy class to implement all of the interfaces,
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   997
     * regardless of what package it is defined in.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   998
     *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
   999
     * <li>For any set of member methods of the specified interfaces
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1000
     * that have the same signature:
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1001
     * <ul>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1002
     * <li>If the return type of any of the methods is a primitive
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1003
     * type or void, then all of the methods must have that same
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1004
     * return type.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1005
     * <li>Otherwise, one of the methods must have a return type that
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1006
     * is assignable to all of the return types of the rest of the
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1007
     * methods.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1008
     * </ul>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1009
     *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1010
     * <li>The resulting proxy class must not exceed any limits imposed
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1011
     * on classes by the virtual machine.  For example, the VM may limit
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1012
     * the number of interfaces that a class may implement to 65535; in
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1013
     * that case, the size of the {@code interfaces} array must not
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1014
     * exceed 65535.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1015
     * </ul>
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1016
     *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1017
     * <p>Note that the order of the specified proxy interfaces is
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1018
     * significant: two requests for a proxy class with the same combination
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1019
     * of interfaces but in a different order will result in two distinct
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1020
     * proxy classes.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
     * @param   loader the class loader to define the proxy class
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
     * @param   interfaces the list of interfaces for the proxy class
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
     *          to implement
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
     * @param   h the invocation handler to dispatch method invocations to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
     * @return  a proxy instance with the specified invocation handler of a
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
     *          proxy class that is defined by the specified class loader
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
     *          and that implements the specified interfaces
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1029
     * @throws  IllegalArgumentException if any of the <a href="#restrictions">
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1030
     *          restrictions</a> on the parameters are violated
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1031
     * @throws  SecurityException if a security manager, <em>s</em>, is present
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1032
     *          and any of the following conditions is met:
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1033
     *          <ul>
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1034
     *          <li> the given {@code loader} is {@code null} and
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1035
     *               the caller's class loader is not {@code null} and the
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1036
     *               invocation of {@link SecurityManager#checkPermission
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1037
     *               s.checkPermission} with
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1038
     *               {@code RuntimePermission("getClassLoader")} permission
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1039
     *               denies access;</li>
20825
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1040
     *          <li> for each proxy interface, {@code intf},
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1041
     *               the caller's class loader is not the same as or an
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1042
     *               ancestor of the class loader for {@code intf} and
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1043
     *               invocation of {@link SecurityManager#checkPackageAccess
20825
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1044
     *               s.checkPackageAccess()} denies access to {@code intf};</li>
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1045
     *          <li> any of the given proxy interfaces is non-public and the
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1046
     *               caller class is not in the same {@linkplain Package runtime package}
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1047
     *               as the non-public interface and the invocation of
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1048
     *               {@link SecurityManager#checkPermission s.checkPermission} with
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1049
     *               {@code ReflectPermission("newProxyInPackage.{package name}")}
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1050
     *               permission denies access.</li>
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1051
     *          </ul>
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
     * @throws  NullPointerException if the {@code interfaces} array
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
     *          argument or any of its elements are {@code null}, or
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
     *          if the invocation handler, {@code h}, is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
     *          {@code null}
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1056
     *
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1057
     * @see <a href="#membership">Package and Module Membership of Proxy Class</a>
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
     */
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
  1059
    @CallerSensitive
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
    public static Object newProxyInstance(ClassLoader loader,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
                                          Class<?>[] interfaces,
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1062
                                          InvocationHandler h) {
17497
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
  1063
        Objects.requireNonNull(h);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1064
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1065
        final List<Class<?>> intfs = List.of(interfaces);  // interfaces cloned
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
  1066
        final SecurityManager sm = System.getSecurityManager();
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1067
        final Class<?> caller = Reflection.getCallerClass();
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
  1068
        if (sm != null) {
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1069
            checkProxyAccess(caller, loader, intfs);
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
  1070
        }
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
  1071
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
         * Look up or generate the designated proxy class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
         */
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1075
        Class<?> cl = new ProxyBuilder(loader, intfs).build();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1077
        return newProxyInstance(cl, caller, h);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1078
    }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1079
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1080
    private static Object newProxyInstance(Class<?> proxyClass, Class<?> caller, InvocationHandler h) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
         * Invoke its constructor with the designated invocation handler.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
        try {
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1085
            final SecurityManager sm = System.getSecurityManager();
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1086
            if (sm != null) {
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1087
                checkNewProxyPermission(caller, proxyClass);
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1088
            }
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1089
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1090
            final Constructor<?> cons = proxyClass.getConstructor(constructorParams);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1091
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1092
                public Void run() {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1093
                    cons.setAccessible(true);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1094
                    return null;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1095
                }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1096
            });
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1097
            return cons.newInstance(new Object[]{h});
22581
e868cde95050 8032779: Update code in java.lang to use newer language features
psandoz
parents: 21655
diff changeset
  1098
        } catch (IllegalAccessException | InstantiationException | NoSuchMethodException e) {
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1099
            throw new InternalError(e.toString(), e);
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1100
        } catch (InvocationTargetException e) {
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1101
            Throwable t = e.getCause();
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1102
            if (t instanceof RuntimeException) {
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1103
                throw (RuntimeException) t;
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
  1104
            } else {
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1105
                throw new InternalError(t.toString(), t);
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
  1106
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1107
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1108
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1109
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1110
    private static void checkNewProxyPermission(Class<?> caller, Class<?> proxyClass) {
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1111
        SecurityManager sm = System.getSecurityManager();
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1112
        if (sm != null) {
18244
a1031f4526b2 8011557: Improve reflection utility classes
mchung
parents: 16923
diff changeset
  1113
            if (ReflectUtil.isNonPublicProxyClass(proxyClass)) {
a1031f4526b2 8011557: Improve reflection utility classes
mchung
parents: 16923
diff changeset
  1114
                ClassLoader ccl = caller.getClassLoader();
a1031f4526b2 8011557: Improve reflection utility classes
mchung
parents: 16923
diff changeset
  1115
                ClassLoader pcl = proxyClass.getClassLoader();
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1116
18244
a1031f4526b2 8011557: Improve reflection utility classes
mchung
parents: 16923
diff changeset
  1117
                // do permission check if the caller is in a different runtime package
a1031f4526b2 8011557: Improve reflection utility classes
mchung
parents: 16923
diff changeset
  1118
                // of the proxy class
a1031f4526b2 8011557: Improve reflection utility classes
mchung
parents: 16923
diff changeset
  1119
                int n = proxyClass.getName().lastIndexOf('.');
a1031f4526b2 8011557: Improve reflection utility classes
mchung
parents: 16923
diff changeset
  1120
                String pkg = (n == -1) ? "" : proxyClass.getName().substring(0, n);
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1121
18244
a1031f4526b2 8011557: Improve reflection utility classes
mchung
parents: 16923
diff changeset
  1122
                n = caller.getName().lastIndexOf('.');
a1031f4526b2 8011557: Improve reflection utility classes
mchung
parents: 16923
diff changeset
  1123
                String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n);
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1124
18244
a1031f4526b2 8011557: Improve reflection utility classes
mchung
parents: 16923
diff changeset
  1125
                if (pcl != ccl || !pkg.equals(callerPkg)) {
a1031f4526b2 8011557: Improve reflection utility classes
mchung
parents: 16923
diff changeset
  1126
                    sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg));
a1031f4526b2 8011557: Improve reflection utility classes
mchung
parents: 16923
diff changeset
  1127
                }
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1128
            }
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1129
        }
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1130
    }
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
  1131
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1132
    /**
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1133
     * Returns the class loader for the given module.
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1134
     */
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1135
    private static ClassLoader getLoader(Module m) {
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1136
        PrivilegedAction<ClassLoader> pa = m::getClassLoader;
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1137
        return AccessController.doPrivileged(pa);
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1138
    }
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1139
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1140
    /**
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1141
     * Returns true if the given class is a proxy class.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1142
     *
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1143
     * @implNote The reliability of this method is important for the ability
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1144
     * to use it to make security decisions, so its implementation should
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1145
     * not just test if the class in question extends {@code Proxy}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1146
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1147
     * @param   cl the class to test
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1148
     * @return  {@code true} if the class is a proxy class and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1149
     *          {@code false} otherwise
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1150
     * @throws  NullPointerException if {@code cl} is {@code null}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1151
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1152
    public static boolean isProxyClass(Class<?> cl) {
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1153
        return Proxy.class.isAssignableFrom(cl) && ProxyClassFactory.isProxyClass(cl);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1154
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1155
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1156
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1157
     * Returns the invocation handler for the specified proxy instance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1158
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1159
     * @param   proxy the proxy instance to return the invocation handler for
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1160
     * @return  the invocation handler for the proxy instance
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1161
     * @throws  IllegalArgumentException if the argument is not a
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1162
     *          proxy instance
20825
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1163
     * @throws  SecurityException if a security manager, <em>s</em>, is present
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1164
     *          and the caller's class loader is not the same as or an
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1165
     *          ancestor of the class loader for the invocation handler
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1166
     *          and invocation of {@link SecurityManager#checkPackageAccess
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1167
     *          s.checkPackageAccess()} denies access to the invocation
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1168
     *          handler's class.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1169
     */
20825
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1170
    @CallerSensitive
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1171
    public static InvocationHandler getInvocationHandler(Object proxy)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1172
        throws IllegalArgumentException
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1173
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1174
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1175
         * Verify that the object is actually a proxy instance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1176
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1177
        if (!isProxyClass(proxy.getClass())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1178
            throw new IllegalArgumentException("not a proxy instance");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1179
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1180
20825
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1181
        final Proxy p = (Proxy) proxy;
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1182
        final InvocationHandler ih = p.h;
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1183
        if (System.getSecurityManager() != null) {
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1184
            Class<?> ihClass = ih.getClass();
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1185
            Class<?> caller = Reflection.getCallerClass();
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1186
            if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(),
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1187
                                                    ihClass.getClassLoader()))
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1188
            {
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1189
                ReflectUtil.checkPackageAccess(ihClass);
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1190
            }
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1191
        }
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1192
3d5429b4b601 8017196: Ensure Proxies are handled appropriately
mchung
parents: 18251
diff changeset
  1193
        return ih;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1194
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1195
36511
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1196
    private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
9d0388c6b336 8142968: Module System implementation
alanb
parents: 34882
diff changeset
  1197
    private static final String PROXY_PACKAGE_PREFIX = ReflectUtil.PROXY_PACKAGE;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1198
}