jdk/src/share/classes/java/lang/reflect/Proxy.java
author mchung
Thu, 16 May 2013 15:08:24 -0700
changeset 17497 e65d73b7ae54
parent 17188 5e58e261911b
child 18251 3743160a4cb8
permissions -rw-r--r--
4487672: (proxy) Proxy constructor should check for null argument Reviewed-by: alanb, lancea
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
14342
8435a30053c1 7197491: update copyright year to match last edit in jdk8 jdk repository
alanb
parents: 10419
diff changeset
     2
 * Copyright (c) 1999, 2011, 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;
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
    32
import java.util.IdentityHashMap;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.util.Map;
17497
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
    34
import java.util.Objects;
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
    35
import java.util.concurrent.atomic.AtomicLong;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
    36
import java.util.function.BiFunction;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import sun.misc.ProxyGenerator;
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
    38
import sun.misc.VM;
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
    39
import sun.reflect.CallerSensitive;
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
    40
import sun.reflect.Reflection;
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
    41
import sun.reflect.misc.ReflectUtil;
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
    42
import sun.security.util.SecurityConstants;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * {@code Proxy} provides static methods for creating dynamic proxy
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 * classes and instances, and it is also the superclass of all
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * dynamic proxy classes created by those methods.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * <p>To create a proxy for some interface {@code Foo}:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 *     InvocationHandler handler = new MyInvocationHandler(...);
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
    52
 *     Class&lt;?&gt; proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
    53
 *     Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
    54
 *                     newInstance(handler);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * </pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * or more simply:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
    59
 *                                          new Class&lt;?&gt;[] { Foo.class },
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 *                                          handler);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * </pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 * class</i> below) is a class that implements a list of interfaces
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 * specified at runtime when the class is created, with behavior as
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * described below.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 * A <i>proxy interface</i> is such an interface that is implemented
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 * by a proxy class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 * A <i>proxy instance</i> is an instance of a proxy class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 * Each proxy instance has an associated <i>invocation handler</i>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 * object, which implements the interface {@link InvocationHandler}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 * A method invocation on a proxy instance through one of its proxy
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * interfaces will be dispatched to the {@link InvocationHandler#invoke
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 * invoke} method of the instance's invocation handler, passing the proxy
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 * instance, a {@code java.lang.reflect.Method} object identifying
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 * the method that was invoked, and an array of type {@code Object}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 * containing the arguments.  The invocation handler processes the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 * encoded method invocation as appropriate and the result that it
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 * returns will be returned as the result of the method invocation on
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
 * the proxy instance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
 * <p>A proxy class has the following properties:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
 * <ul>
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
    88
 * <li>Proxy classes are <em>public, final, and not abstract</em> if
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
    89
 * all proxy interfaces are public.</li>
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
    90
 *
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
    91
 * <li>Proxy classes are <em>non-public, final, and not abstract</em> if
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
    92
 * any of the proxy interfaces is non-public.</li>
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
 * <li>The unqualified name of a proxy class is unspecified.  The space
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
 * of class names that begin with the string {@code "$Proxy"}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
 * should be, however, reserved for proxy classes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
 * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
 * <li>A proxy class implements exactly the interfaces specified at its
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
 * creation, in the same order.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
 * <li>If a proxy class implements a non-public interface, then it will
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
 * be defined in the same package as that interface.  Otherwise, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
 * package of a proxy class is also unspecified.  Note that package
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
 * sealing will not prevent a proxy class from being successfully defined
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
 * in a particular package at runtime, and neither will classes already
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
 * defined by the same class loader and the same package with particular
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
 * signers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
 * <li>Since a proxy class implements all of the interfaces specified at
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
 * its creation, invoking {@code getInterfaces} on its
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
 * {@code Class} object will return an array containing the same
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
 * list of interfaces (in the order specified at its creation), invoking
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
 * {@code getMethods} on its {@code Class} object will return
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
 * an array of {@code Method} objects that include all of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
 * methods in those interfaces, and invoking {@code getMethod} will
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
 * find methods in the proxy interfaces as would be expected.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
 * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
 * return true if it is passed a proxy class-- a class returned by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
 * {@code Proxy.getProxyClass} or the class of an object returned by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
 * {@code Proxy.newProxyInstance}-- and false otherwise.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
 * <li>The {@code java.security.ProtectionDomain} of a proxy class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
 * is the same as that of system classes loaded by the bootstrap class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
 * loader, such as {@code java.lang.Object}, because the code for a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
 * proxy class is generated by trusted system code.  This protection
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
 * domain will typically be granted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
 * {@code java.security.AllPermission}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
 * <li>Each proxy class has one public constructor that takes one argument,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
 * an implementation of the interface {@link InvocationHandler}, to set
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
 * the invocation handler for a proxy instance.  Rather than having to use
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
 * the reflection API to access the public constructor, a proxy instance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
 * can be also be created by calling the {@link Proxy#newProxyInstance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
 * Proxy.newProxyInstance} method, which combines the actions of calling
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
 * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
 * constructor with an invocation handler.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
 * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
 * <p>A proxy instance has the following properties:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
 * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
 * <li>Given a proxy instance {@code proxy} and one of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
 * interfaces implemented by its proxy class {@code Foo}, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
 * following expression will return true:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
 * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
 *     {@code proxy instanceof Foo}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
 * </pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
 * and the following cast operation will succeed (rather than throwing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
 * a {@code ClassCastException}):
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
 * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
 *     {@code (Foo) proxy}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
 * </pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
 * <li>Each proxy instance has an associated invocation handler, the one
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
 * that was passed to its constructor.  The static
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
 * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
 * will return the invocation handler associated with the proxy instance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
 * passed as its argument.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
 * <li>An interface method invocation on a proxy instance will be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
 * encoded and dispatched to the invocation handler's {@link
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
 * InvocationHandler#invoke invoke} method as described in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
 * documentation for that method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
 * <li>An invocation of the {@code hashCode},
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
 * {@code equals}, or {@code toString} methods declared in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
 * {@code java.lang.Object} on a proxy instance will be encoded and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
 * dispatched to the invocation handler's {@code invoke} method in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
 * the same manner as interface method invocations are encoded and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
 * dispatched, as described above.  The declaring class of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
 * {@code Method} object passed to {@code invoke} will be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
 * {@code java.lang.Object}.  Other public methods of a proxy
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
 * instance inherited from {@code java.lang.Object} are not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
 * overridden by a proxy class, so invocations of those methods behave
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
 * like they do for instances of {@code java.lang.Object}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
 * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
 * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
 * <p>When two or more interfaces of a proxy class contain a method with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
 * the same name and parameter signature, the order of the proxy class's
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
 * interfaces becomes significant.  When such a <i>duplicate method</i>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
 * is invoked on a proxy instance, the {@code Method} object passed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
 * to the invocation handler will not necessarily be the one whose
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
 * declaring class is assignable from the reference type of the interface
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
 * that the proxy's method was invoked through.  This limitation exists
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
 * because the corresponding method implementation in the generated proxy
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
 * class cannot determine which interface it was invoked through.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
 * Therefore, when a duplicate method is invoked on a proxy instance,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
 * the {@code Method} object for the method in the foremost interface
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
 * that contains the method (either directly or inherited through a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
 * superinterface) in the proxy class's list of interfaces is passed to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
 * the invocation handler's {@code invoke} method, regardless of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
 * reference type through which the method invocation occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
 * <p>If a proxy interface contains a method with the same name and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
 * parameter signature as the {@code hashCode}, {@code equals},
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
 * or {@code toString} methods of {@code java.lang.Object},
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
 * when such a method is invoked on a proxy instance, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
 * {@code Method} object passed to the invocation handler will have
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
 * {@code java.lang.Object} as its declaring class.  In other words,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
 * the public, non-final methods of {@code java.lang.Object}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
 * logically precede all of the proxy interfaces for the determination of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
 * which {@code Method} object to pass to the invocation handler.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
 * <p>Note also that when a duplicate method is dispatched to an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
 * invocation handler, the {@code invoke} method may only throw
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
 * checked exception types that are assignable to one of the exception
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
 * types in the {@code throws} clause of the method in <i>all</i> of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
 * the proxy interfaces that it can be invoked through.  If the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
 * {@code invoke} method throws a checked exception that is not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
 * assignable to any of the exception types declared by the method in one
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
 * of the proxy interfaces that it can be invoked through, then an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
 * unchecked {@code UndeclaredThrowableException} will be thrown by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
 * the invocation on the proxy instance.  This restriction means that not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
 * all of the exception types returned by invoking
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
 * {@code getExceptionTypes} on the {@code Method} object
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
 * passed to the {@code invoke} method can necessarily be thrown
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
 * successfully by the {@code invoke} method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
 * @author      Peter Jones
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
 * @see         InvocationHandler
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
 * @since       1.3
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
public class Proxy implements java.io.Serializable {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
    private static final long serialVersionUID = -2222568056686623797L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
    /** parameter types of a proxy class constructor */
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   233
    private static final Class<?>[] constructorParams =
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
        { InvocationHandler.class };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   236
    /**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   237
     * a cache of proxy classes
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   238
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   239
    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   240
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
     * the invocation handler for this proxy instance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
     * @serial
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
    protected InvocationHandler h;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
     * Prohibits instantiation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
    private Proxy() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
     * Constructs a new {@code Proxy} instance from a subclass
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
     * (typically, a dynamic proxy class) with the specified value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
     * for its invocation handler.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
     *
17497
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
   259
     * @param  h the invocation handler for this proxy instance
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
   260
     *
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
   261
     * @throws NullPointerException if the given invocation handler, {@code h},
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
   262
     *         is {@code null}.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
    protected Proxy(InvocationHandler h) {
17497
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
   265
        Objects.requireNonNull(h);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
        this.h = h;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
     * Returns the {@code java.lang.Class} object for a proxy class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
     * given a class loader and an array of interfaces.  The proxy class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
     * 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
   273
     * 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
   274
     * 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
   275
     * 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
   276
     * class loader, then the existing proxy class will be returned; otherwise,
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
     * a proxy class for those interfaces will be generated dynamically
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
     * and defined by the class loader.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
     * <p>There are several restrictions on the parameters that may be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
     * passed to {@code Proxy.getProxyClass}:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
     * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
     * <li>All of the {@code Class} objects in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
     * {@code interfaces} array must represent interfaces, not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
     * classes or primitive types.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
     * <li>No two elements in the {@code interfaces} array may
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
     * refer to identical {@code Class} objects.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
     * <li>All of the interface types must be visible by name through the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
     * specified class loader.  In other words, for class loader
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
     * {@code cl} and every interface {@code i}, the following
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
     * expression must be true:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
     * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
     *     Class.forName(i.getName(), false, cl) == i
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
     * </pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
     * <li>All non-public interfaces must be in the same package;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
     * otherwise, it would not be possible for the proxy class to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
     * implement all of the interfaces, regardless of what package it is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
     * defined in.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
     * <li>For any set of member methods of the specified interfaces
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
     * that have the same signature:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
     * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
     * <li>If the return type of any of the methods is a primitive
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
     * type or void, then all of the methods must have that same
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
     * return type.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
     * <li>Otherwise, one of the methods must have a return type that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
     * is assignable to all of the return types of the rest of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
     * methods.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
     * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
     * <li>The resulting proxy class must not exceed any limits imposed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
     * on classes by the virtual machine.  For example, the VM may limit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
     * the number of interfaces that a class may implement to 65535; in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
     * that case, the size of the {@code interfaces} array must not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
     * exceed 65535.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
     * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
     * <p>If any of these restrictions are violated,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
     * {@code Proxy.getProxyClass} will throw an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
     * {@code IllegalArgumentException}.  If the {@code interfaces}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
     * array argument or any of its elements are {@code null}, a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
     * {@code NullPointerException} will be thrown.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
     * <p>Note that the order of the specified proxy interfaces is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
     * significant: two requests for a proxy class with the same combination
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
     * of interfaces but in a different order will result in two distinct
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
     * proxy classes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
     * @param   loader the class loader to define the proxy class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
     * @param   interfaces the list of interfaces for the proxy class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
     *          to implement
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
     * @return  a proxy class that is defined in the specified class loader
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
     *          and that implements the specified interfaces
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
     * @throws  IllegalArgumentException if any of the restrictions on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
     *          parameters that may be passed to {@code getProxyClass}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
     *          are violated
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   341
     * @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
   342
     *          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
   343
     *          <ul>
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   344
     *             <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
   345
     *             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
   346
     *             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
   347
     *             s.checkPermission} with
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   348
     *             {@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
   349
     *             denies access.</li>
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   350
     *             <li> the caller's class loader is not the same as or an
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   351
     *             ancestor of the class loader for the current class and
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   352
     *             invocation of {@link SecurityManager#checkPackageAccess
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   353
     *             s.checkPackageAccess()} denies access to any one of the
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   354
     *             given proxy interfaces.</li>
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   355
     *          </ul>
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   356
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
     * @throws  NullPointerException if the {@code interfaces} array
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
     *          argument or any of its elements are {@code null}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
     */
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   360
    @CallerSensitive
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
    public static Class<?> getProxyClass(ClassLoader loader,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
                                         Class<?>... interfaces)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        throws IllegalArgumentException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
    {
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   365
        SecurityManager sm = System.getSecurityManager();
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   366
        if (sm != null) {
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   367
            checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   368
        }
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   369
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   370
        return getProxyClass0(loader, interfaces);
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   371
    }
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
    /*
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   374
     * Check permissions required to create a Proxy class.
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   375
     *
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   376
     * 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
   377
     * Class.forName (VM will invoke ClassLoader.checkPackageAccess):
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   378
     * 1. "getClassLoader" permission check if loader == null
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   379
     * 2. checkPackageAccess on the interfaces it implements
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   380
     *
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   381
     * 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
   382
     * the package access check on the interfaces it implements
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   383
     * as in Class.getConstructor.
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   384
     *
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   385
     * 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
   386
     * 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
   387
     * 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
   388
     * will throw IllegalAccessError when the generated proxy class is
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   389
     * being defined via the defineClass0 method.
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   390
     */
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   391
    private static void checkProxyAccess(Class<?> caller,
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   392
                                         ClassLoader loader,
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   393
                                         Class<?>... interfaces)
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   394
    {
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   395
        SecurityManager sm = System.getSecurityManager();
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   396
        if (sm != null) {
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   397
            ClassLoader ccl = caller.getClassLoader();
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   398
            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
   399
                sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   400
            }
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   401
            ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   402
        }
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   403
    }
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   404
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   405
    /**
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   406
     * Generate a proxy class.  Must call the checkProxyAccess method
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   407
     * to perform permission checks before calling this.
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   408
     */
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   409
    private static Class<?> getProxyClass0(ClassLoader loader,
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   410
                                           Class<?>... interfaces) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
        if (interfaces.length > 65535) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
            throw new IllegalArgumentException("interface limit exceeded");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   415
        // If the proxy class defined by the given loader implementing
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   416
        // the given interfaces exists, this will simply return the cached copy;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   417
        // otherwise, it will create the proxy class via the ProxyClassFactory
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   418
        return proxyClassCache.get(loader, interfaces);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   419
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   420
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
     * 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
   423
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   424
    private static final Object key0 = new Object();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   425
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   426
    /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   427
     * 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
   428
     * that implement 1 or 2 interfaces.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   429
     */
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
17188
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
     * 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
   433
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   434
    private static final class Key1 extends WeakReference<Class<?>> {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   435
        private final int hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   436
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   437
        Key1(Class<?> intf) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   438
            super(intf);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   439
            this.hash = intf.hashCode();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   440
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   442
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   443
        public int hashCode() {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   444
            return hash;
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
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   447
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   448
        public boolean equals(Object obj) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   449
            Class<?> intf;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   450
            return this == obj ||
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   451
                   obj != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   452
                   obj.getClass() == Key1.class &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   453
                   (intf = get()) != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   454
                   intf == ((Key1) obj).get();
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
    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   458
    /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   459
     * 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
   460
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   461
    private static final class Key2 extends WeakReference<Class<?>> {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   462
        private final int hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   463
        private final WeakReference<Class<?>> ref2;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   464
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   465
        Key2(Class<?> intf1, Class<?> intf2) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   466
            super(intf1);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   467
            hash = 31 * intf1.hashCode() + intf2.hashCode();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   468
            ref2 = new WeakReference<Class<?>>(intf2);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   469
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   470
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   471
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   472
        public int hashCode() {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   473
            return hash;
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
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   476
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   477
        public boolean equals(Object obj) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   478
            Class<?> intf1, intf2;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   479
            return this == obj ||
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   480
                   obj != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   481
                   obj.getClass() == Key2.class &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   482
                   (intf1 = get()) != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   483
                   intf1 == ((Key2) obj).get() &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   484
                   (intf2 = ref2.get()) != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   485
                   intf2 == ((Key2) obj).ref2.get();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   486
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   487
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   488
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   489
    /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   490
     * 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
   491
     * (used here for 3 or more only)
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   492
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   493
    private static final class KeyX {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   494
        private final int hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   495
        private final WeakReference<Class<?>>[] refs;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   496
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   497
        KeyX(Class<?>[] interfaces) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   498
            hash = Arrays.hashCode(interfaces);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   499
            refs = new WeakReference[interfaces.length];
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   500
            for (int i = 0; i < interfaces.length; i++) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   501
                refs[i] = new WeakReference<>(interfaces[i]);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
            }
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
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   506
        public int hashCode() {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   507
            return hash;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   508
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   510
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   511
        public boolean equals(Object obj) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   512
            return this == obj ||
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   513
                   obj != null &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   514
                   obj.getClass() == KeyX.class &&
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   515
                   equals(refs, ((KeyX) obj).refs);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   518
        private static boolean equals(WeakReference<Class<?>>[] refs1,
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   519
                                      WeakReference<Class<?>>[] refs2) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   520
            if (refs1.length != refs2.length) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   521
                return false;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   522
            }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   523
            for (int i = 0; i < refs1.length; i++) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   524
                Class<?> intf = refs1[i].get();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   525
                if (intf == null || intf != refs2[i].get()) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   526
                    return false;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
                }
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   528
            }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   529
            return true;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   530
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   531
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   532
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   533
    /**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   534
     * 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
   535
     * Class objects representing interfaces are weakly referenced.
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
    private static final class KeyFactory
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   538
        implements BiFunction<ClassLoader, Class<?>[], Object>
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   539
    {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   540
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   541
        public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   542
            switch (interfaces.length) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   543
                case 1: return new Key1(interfaces[0]); // the most frequent
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   544
                case 2: return new Key2(interfaces[0], interfaces[1]);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   545
                case 0: return key0;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   546
                default: return new KeyX(interfaces);
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
        }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   549
    }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   550
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   551
    /**
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   552
     * A factory function that generates, defines and returns the proxy class given
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   553
     * the ClassLoader and array of interfaces.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   554
     */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   555
    private static final class ProxyClassFactory
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   556
        implements BiFunction<ClassLoader, Class<?>[], Class<?>>
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   557
    {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   558
        // prefix for all proxy class names
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   559
        private static final String proxyClassNamePrefix = "$Proxy";
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   560
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   561
        // 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
   562
        private static final AtomicLong nextUniqueNumber = new AtomicLong();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   563
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   564
        @Override
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   565
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   566
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   567
            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   568
            for (Class<?> intf : interfaces) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   569
                /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   570
                 * Verify that the class loader resolves the name of this
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   571
                 * interface to the same Class object.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   572
                 */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   573
                Class<?> interfaceClass = null;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   574
                try {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   575
                    interfaceClass = Class.forName(intf.getName(), false, loader);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   576
                } catch (ClassNotFoundException e) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
                }
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   578
                if (interfaceClass != intf) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   579
                    throw new IllegalArgumentException(
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   580
                        intf + " is not visible from class loader");
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   581
                }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   582
                /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   583
                 * Verify that the Class object actually represents an
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   584
                 * interface.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   585
                 */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   586
                if (!interfaceClass.isInterface()) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   587
                    throw new IllegalArgumentException(
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   588
                        interfaceClass.getName() + " is not an interface");
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   589
                }
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
                 * Verify that this interface is not a duplicate.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   592
                 */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   593
                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   594
                    throw new IllegalArgumentException(
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   595
                        "repeated interface: " + interfaceClass.getName());
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   596
                }
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   597
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
            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
   600
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
             * Record the package of a non-public proxy interface so that the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
             * proxy class will be defined in the same package.  Verify that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
             * all non-public proxy interfaces are in the same package.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
             */
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   607
            for (Class<?> intf : interfaces) {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   608
                int flags = intf.getModifiers();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
                if (!Modifier.isPublic(flags)) {
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   610
                    accessFlags = Modifier.FINAL;
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   611
                    String name = intf.getName();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
                    int n = name.lastIndexOf('.');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
                    if (proxyPkg == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
                        proxyPkg = pkg;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
                    } else if (!pkg.equals(proxyPkg)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
                        throw new IllegalArgumentException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
                            "non-public interfaces from different packages");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   623
            if (proxyPkg == null) {
16108
e5fcdadc69b2 8006882: Proxy generated classes in sun.proxy package breaks JMockit
mchung
parents: 16100
diff changeset
   624
                // if no non-public proxy interfaces, use com.sun.proxy package
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   625
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   628
            /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   629
             * 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
   630
             */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   631
            long num = nextUniqueNumber.getAndIncrement();
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   632
            String proxyName = proxyPkg + proxyClassNamePrefix + num;
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   633
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   634
            /*
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   635
             * Generate the specified proxy class.
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   636
             */
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   637
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   638
                proxyName, interfaces, accessFlags);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   639
            try {
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   640
                return defineClass0(loader, proxyName,
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   641
                                    proxyClassFile, 0, proxyClassFile.length);
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   642
            } catch (ClassFormatError e) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
                /*
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   644
                 * 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
   645
                 * proxy class generation code) there was some other
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   646
                 * 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
   647
                 * class creation (such as virtual machine limitations
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   648
                 * exceeded).
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
                 */
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   650
                throw new IllegalArgumentException(e.toString());
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
     * Returns an instance of a proxy class for the specified interfaces
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
     * 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
   658
     * handler.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
     * <p>{@code Proxy.newProxyInstance} throws
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
     * {@code IllegalArgumentException} for the same reasons that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
     * {@code Proxy.getProxyClass} does.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
     * @param   loader the class loader to define the proxy class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
     * @param   interfaces the list of interfaces for the proxy class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
     *          to implement
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
     * @param   h the invocation handler to dispatch method invocations to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
     * @return  a proxy instance with the specified invocation handler of a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
     *          proxy class that is defined by the specified class loader
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
     *          and that implements the specified interfaces
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
     * @throws  IllegalArgumentException if any of the restrictions on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
     *          parameters that may be passed to {@code getProxyClass}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
     *          are violated
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   674
     * @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
   675
     *          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
   676
     *          <ul>
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   677
     *          <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
   678
     *               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
   679
     *               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
   680
     *               s.checkPermission} with
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   681
     *               {@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
   682
     *               denies access;</li>
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   683
     *          <li> the caller's class loader is not the same as or an
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   684
     *               ancestor of the class loader for the current class and
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   685
     *               invocation of {@link SecurityManager#checkPackageAccess
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   686
     *               s.checkPackageAccess()} denies access to any one of the
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   687
     *               given proxy interfaces.</li>
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   688
     *          <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
   689
     *               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
   690
     *               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
   691
     *               {@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
   692
     *               {@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
   693
     *               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
   694
     *          </ul>
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
     * @throws  NullPointerException if the {@code interfaces} array
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
     *          argument or any of its elements are {@code null}, or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
     *          if the invocation handler, {@code h}, is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
     *          {@code null}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
     */
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   700
    @CallerSensitive
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
    public static Object newProxyInstance(ClassLoader loader,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
                                          Class<?>[] interfaces,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
                                          InvocationHandler h)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
        throws IllegalArgumentException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
    {
17497
e65d73b7ae54 4487672: (proxy) Proxy constructor should check for null argument
mchung
parents: 17188
diff changeset
   706
        Objects.requireNonNull(h);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   708
        final SecurityManager sm = System.getSecurityManager();
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   709
        if (sm != null) {
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   710
            checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   711
        }
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   712
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
         * Look up or generate the designated proxy class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
         */
16906
44dfee24cb71 8010117: Annotate jdk caller sensitive methods with @sun.reflect.CallerSensitive
mchung
parents: 16108
diff changeset
   716
        Class<?> cl = getProxyClass0(loader, interfaces);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
         * Invoke its constructor with the designated invocation handler.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
        try {
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   722
            if (sm != null) {
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   723
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   724
            }
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   725
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   726
            final Constructor<?> cons = cl.getConstructor(constructorParams);
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   727
            final InvocationHandler ih = h;
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   728
            if (!Modifier.isPublic(cl.getModifiers())) {
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   729
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   730
                    public Void run() {
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   731
                        cons.setAccessible(true);
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   732
                        return null;
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   733
                    }
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   734
                });
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   735
            }
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   736
            return cons.newInstance(new Object[]{h});
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   737
        } catch (IllegalAccessException|InstantiationException e) {
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   738
            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
   739
        } catch (InvocationTargetException e) {
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   740
            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
   741
            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
   742
                throw (RuntimeException) t;
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   743
            } else {
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   744
                throw new InternalError(t.toString(), t);
16087
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   745
            }
89b565a23835 7197546: (proxy) Reflect about creating reflective proxies
mchung
parents: 10419
diff changeset
   746
        } catch (NoSuchMethodException e) {
10419
12c063b39232 7084245: Update usages of InternalError to use exception chaining
sherman
parents: 10342
diff changeset
   747
            throw new InternalError(e.toString(), e);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
16923
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   751
    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
   752
        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
   753
        if (sm != null) {
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   754
            String pcn = proxyClass.getName();
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   755
            if (pcn.startsWith(ReflectUtil.PROXY_PACKAGE + ".")) {
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   756
                // all proxy interfaces are public
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   757
                return;
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   758
            }
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   759
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   760
            ClassLoader ccl = caller.getClassLoader();
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   761
            ClassLoader pcl = proxyClass.getClassLoader();
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   762
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   763
            // do permission check if the caller is in a different runtime package
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   764
            // of the proxy class
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   765
            int n = pcn.lastIndexOf('.');
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   766
            String pkg = (n == -1) ? "" : pcn.substring(0, n);
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   767
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   768
            n = caller.getName().lastIndexOf('.');
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   769
            String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n);
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   770
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   771
            if (pcl != ccl || !pkg.equals(callerPkg)) {
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   772
                sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg));
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   773
            }
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   774
        }
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   775
    }
50bfa0defec2 8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
mchung
parents: 16906
diff changeset
   776
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
     * Returns true if and only if the specified class was dynamically
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
     * generated to be a proxy class using the {@code getProxyClass}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
     * method or the {@code newProxyInstance} method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
     * <p>The reliability of this method is important for the ability
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
     * to use it to make security decisions, so its implementation should
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
     * not just test if the class in question extends {@code Proxy}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
     * @param   cl the class to test
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
     * @return  {@code true} if the class is a proxy class and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
     *          {@code false} otherwise
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
     * @throws  NullPointerException if {@code cl} is {@code null}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
    public static boolean isProxyClass(Class<?> cl) {
17188
5e58e261911b 7123493: (proxy) Proxy.getProxyClass doesn't scale under high load
plevart
parents: 16923
diff changeset
   792
        return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
     * Returns the invocation handler for the specified proxy instance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
     * @param   proxy the proxy instance to return the invocation handler for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
     * @return  the invocation handler for the proxy instance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
     * @throws  IllegalArgumentException if the argument is not a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
     *          proxy instance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
    public static InvocationHandler getInvocationHandler(Object proxy)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
        throws IllegalArgumentException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
         * Verify that the object is actually a proxy instance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
        if (!isProxyClass(proxy.getClass())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
            throw new IllegalArgumentException("not a proxy instance");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
        Proxy p = (Proxy) proxy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
        return p.h;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
10342
ca0984bc9d32 7077389: Reflection classes do not build with javac -Xlint:all -Werror
jjg
parents: 9035
diff changeset
   817
    private static native Class<?> defineClass0(ClassLoader loader, String name,
ca0984bc9d32 7077389: Reflection classes do not build with javac -Xlint:all -Werror
jjg
parents: 9035
diff changeset
   818
                                                byte[] b, int off, int len);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
}