rt/emul/mini/src/main/java/java/lang/reflect/Proxy.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 26 Feb 2013 16:54:16 +0100
changeset 772 d382dacfd73f
parent 604 emul/mini/src/main/java/java/lang/reflect/Proxy.java@3fcc279c921b
child 1378 9ee9b36adb53
permissions -rw-r--r--
Moving modules around so the runtime is under one master pom and can be built without building other modules that are in the repository
     1 /*
     2  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.lang.reflect;
    27 
    28 
    29 /**
    30  * {@code Proxy} provides static methods for creating dynamic proxy
    31  * classes and instances, and it is also the superclass of all
    32  * dynamic proxy classes created by those methods.
    33  *
    34  * <p>To create a proxy for some interface {@code Foo}:
    35  * <pre>
    36  *     InvocationHandler handler = new MyInvocationHandler(...);
    37  *     Class proxyClass = Proxy.getProxyClass(
    38  *         Foo.class.getClassLoader(), new Class[] { Foo.class });
    39  *     Foo f = (Foo) proxyClass.
    40  *         getConstructor(new Class[] { InvocationHandler.class }).
    41  *         newInstance(new Object[] { handler });
    42  * </pre>
    43  * or more simply:
    44  * <pre>
    45  *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
    46  *                                          new Class[] { Foo.class },
    47  *                                          handler);
    48  * </pre>
    49  *
    50  * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
    51  * class</i> below) is a class that implements a list of interfaces
    52  * specified at runtime when the class is created, with behavior as
    53  * described below.
    54  *
    55  * A <i>proxy interface</i> is such an interface that is implemented
    56  * by a proxy class.
    57  *
    58  * A <i>proxy instance</i> is an instance of a proxy class.
    59  *
    60  * Each proxy instance has an associated <i>invocation handler</i>
    61  * object, which implements the interface {@link InvocationHandler}.
    62  * A method invocation on a proxy instance through one of its proxy
    63  * interfaces will be dispatched to the {@link InvocationHandler#invoke
    64  * invoke} method of the instance's invocation handler, passing the proxy
    65  * instance, a {@code java.lang.reflect.Method} object identifying
    66  * the method that was invoked, and an array of type {@code Object}
    67  * containing the arguments.  The invocation handler processes the
    68  * encoded method invocation as appropriate and the result that it
    69  * returns will be returned as the result of the method invocation on
    70  * the proxy instance.
    71  *
    72  * <p>A proxy class has the following properties:
    73  *
    74  * <ul>
    75  * <li>Proxy classes are public, final, and not abstract.
    76  *
    77  * <li>The unqualified name of a proxy class is unspecified.  The space
    78  * of class names that begin with the string {@code "$Proxy"}
    79  * should be, however, reserved for proxy classes.
    80  *
    81  * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
    82  *
    83  * <li>A proxy class implements exactly the interfaces specified at its
    84  * creation, in the same order.
    85  *
    86  * <li>If a proxy class implements a non-public interface, then it will
    87  * be defined in the same package as that interface.  Otherwise, the
    88  * package of a proxy class is also unspecified.  Note that package
    89  * sealing will not prevent a proxy class from being successfully defined
    90  * in a particular package at runtime, and neither will classes already
    91  * defined by the same class loader and the same package with particular
    92  * signers.
    93  *
    94  * <li>Since a proxy class implements all of the interfaces specified at
    95  * its creation, invoking {@code getInterfaces} on its
    96  * {@code Class} object will return an array containing the same
    97  * list of interfaces (in the order specified at its creation), invoking
    98  * {@code getMethods} on its {@code Class} object will return
    99  * an array of {@code Method} objects that include all of the
   100  * methods in those interfaces, and invoking {@code getMethod} will
   101  * find methods in the proxy interfaces as would be expected.
   102  *
   103  * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
   104  * return true if it is passed a proxy class-- a class returned by
   105  * {@code Proxy.getProxyClass} or the class of an object returned by
   106  * {@code Proxy.newProxyInstance}-- and false otherwise.
   107  *
   108  * <li>The {@code java.security.ProtectionDomain} of a proxy class
   109  * is the same as that of system classes loaded by the bootstrap class
   110  * loader, such as {@code java.lang.Object}, because the code for a
   111  * proxy class is generated by trusted system code.  This protection
   112  * domain will typically be granted
   113  * {@code java.security.AllPermission}.
   114  *
   115  * <li>Each proxy class has one public constructor that takes one argument,
   116  * an implementation of the interface {@link InvocationHandler}, to set
   117  * the invocation handler for a proxy instance.  Rather than having to use
   118  * the reflection API to access the public constructor, a proxy instance
   119  * can be also be created by calling the {@link Proxy#newProxyInstance
   120  * Proxy.newProxyInstance} method, which combines the actions of calling
   121  * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
   122  * constructor with an invocation handler.
   123  * </ul>
   124  *
   125  * <p>A proxy instance has the following properties:
   126  *
   127  * <ul>
   128  * <li>Given a proxy instance {@code proxy} and one of the
   129  * interfaces implemented by its proxy class {@code Foo}, the
   130  * following expression will return true:
   131  * <pre>
   132  *     {@code proxy instanceof Foo}
   133  * </pre>
   134  * and the following cast operation will succeed (rather than throwing
   135  * a {@code ClassCastException}):
   136  * <pre>
   137  *     {@code (Foo) proxy}
   138  * </pre>
   139  *
   140  * <li>Each proxy instance has an associated invocation handler, the one
   141  * that was passed to its constructor.  The static
   142  * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
   143  * will return the invocation handler associated with the proxy instance
   144  * passed as its argument.
   145  *
   146  * <li>An interface method invocation on a proxy instance will be
   147  * encoded and dispatched to the invocation handler's {@link
   148  * InvocationHandler#invoke invoke} method as described in the
   149  * documentation for that method.
   150  *
   151  * <li>An invocation of the {@code hashCode},
   152  * {@code equals}, or {@code toString} methods declared in
   153  * {@code java.lang.Object} on a proxy instance will be encoded and
   154  * dispatched to the invocation handler's {@code invoke} method in
   155  * the same manner as interface method invocations are encoded and
   156  * dispatched, as described above.  The declaring class of the
   157  * {@code Method} object passed to {@code invoke} will be
   158  * {@code java.lang.Object}.  Other public methods of a proxy
   159  * instance inherited from {@code java.lang.Object} are not
   160  * overridden by a proxy class, so invocations of those methods behave
   161  * like they do for instances of {@code java.lang.Object}.
   162  * </ul>
   163  *
   164  * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
   165  *
   166  * <p>When two or more interfaces of a proxy class contain a method with
   167  * the same name and parameter signature, the order of the proxy class's
   168  * interfaces becomes significant.  When such a <i>duplicate method</i>
   169  * is invoked on a proxy instance, the {@code Method} object passed
   170  * to the invocation handler will not necessarily be the one whose
   171  * declaring class is assignable from the reference type of the interface
   172  * that the proxy's method was invoked through.  This limitation exists
   173  * because the corresponding method implementation in the generated proxy
   174  * class cannot determine which interface it was invoked through.
   175  * Therefore, when a duplicate method is invoked on a proxy instance,
   176  * the {@code Method} object for the method in the foremost interface
   177  * that contains the method (either directly or inherited through a
   178  * superinterface) in the proxy class's list of interfaces is passed to
   179  * the invocation handler's {@code invoke} method, regardless of the
   180  * reference type through which the method invocation occurred.
   181  *
   182  * <p>If a proxy interface contains a method with the same name and
   183  * parameter signature as the {@code hashCode}, {@code equals},
   184  * or {@code toString} methods of {@code java.lang.Object},
   185  * when such a method is invoked on a proxy instance, the
   186  * {@code Method} object passed to the invocation handler will have
   187  * {@code java.lang.Object} as its declaring class.  In other words,
   188  * the public, non-final methods of {@code java.lang.Object}
   189  * logically precede all of the proxy interfaces for the determination of
   190  * which {@code Method} object to pass to the invocation handler.
   191  *
   192  * <p>Note also that when a duplicate method is dispatched to an
   193  * invocation handler, the {@code invoke} method may only throw
   194  * checked exception types that are assignable to one of the exception
   195  * types in the {@code throws} clause of the method in <i>all</i> of
   196  * the proxy interfaces that it can be invoked through.  If the
   197  * {@code invoke} method throws a checked exception that is not
   198  * assignable to any of the exception types declared by the method in one
   199  * of the proxy interfaces that it can be invoked through, then an
   200  * unchecked {@code UndeclaredThrowableException} will be thrown by
   201  * the invocation on the proxy instance.  This restriction means that not
   202  * all of the exception types returned by invoking
   203  * {@code getExceptionTypes} on the {@code Method} object
   204  * passed to the {@code invoke} method can necessarily be thrown
   205  * successfully by the {@code invoke} method.
   206  *
   207  * @author      Peter Jones
   208  * @see         InvocationHandler
   209  * @since       1.3
   210  */
   211 public class Proxy implements java.io.Serializable {
   212 
   213     private static final long serialVersionUID = -2222568056686623797L;
   214 
   215 
   216 
   217     /**
   218      * the invocation handler for this proxy instance.
   219      * @serial
   220      */
   221     protected InvocationHandler h;
   222 
   223     /**
   224      * Prohibits instantiation.
   225      */
   226     private Proxy() {
   227     }
   228 
   229     /**
   230      * Constructs a new {@code Proxy} instance from a subclass
   231      * (typically, a dynamic proxy class) with the specified value
   232      * for its invocation handler.
   233      *
   234      * @param   h the invocation handler for this proxy instance
   235      */
   236     protected Proxy(InvocationHandler h) {
   237         this.h = h;
   238     }
   239 
   240     /**
   241      * Returns the {@code java.lang.Class} object for a proxy class
   242      * given a class loader and an array of interfaces.  The proxy class
   243      * will be defined by the specified class loader and will implement
   244      * all of the supplied interfaces.  If a proxy class for the same
   245      * permutation of interfaces has already been defined by the class
   246      * loader, then the existing proxy class will be returned; otherwise,
   247      * a proxy class for those interfaces will be generated dynamically
   248      * and defined by the class loader.
   249      *
   250      * <p>There are several restrictions on the parameters that may be
   251      * passed to {@code Proxy.getProxyClass}:
   252      *
   253      * <ul>
   254      * <li>All of the {@code Class} objects in the
   255      * {@code interfaces} array must represent interfaces, not
   256      * classes or primitive types.
   257      *
   258      * <li>No two elements in the {@code interfaces} array may
   259      * refer to identical {@code Class} objects.
   260      *
   261      * <li>All of the interface types must be visible by name through the
   262      * specified class loader.  In other words, for class loader
   263      * {@code cl} and every interface {@code i}, the following
   264      * expression must be true:
   265      * <pre>
   266      *     Class.forName(i.getName(), false, cl) == i
   267      * </pre>
   268      *
   269      * <li>All non-public interfaces must be in the same package;
   270      * otherwise, it would not be possible for the proxy class to
   271      * implement all of the interfaces, regardless of what package it is
   272      * defined in.
   273      *
   274      * <li>For any set of member methods of the specified interfaces
   275      * that have the same signature:
   276      * <ul>
   277      * <li>If the return type of any of the methods is a primitive
   278      * type or void, then all of the methods must have that same
   279      * return type.
   280      * <li>Otherwise, one of the methods must have a return type that
   281      * is assignable to all of the return types of the rest of the
   282      * methods.
   283      * </ul>
   284      *
   285      * <li>The resulting proxy class must not exceed any limits imposed
   286      * on classes by the virtual machine.  For example, the VM may limit
   287      * the number of interfaces that a class may implement to 65535; in
   288      * that case, the size of the {@code interfaces} array must not
   289      * exceed 65535.
   290      * </ul>
   291      *
   292      * <p>If any of these restrictions are violated,
   293      * {@code Proxy.getProxyClass} will throw an
   294      * {@code IllegalArgumentException}.  If the {@code interfaces}
   295      * array argument or any of its elements are {@code null}, a
   296      * {@code NullPointerException} will be thrown.
   297      *
   298      * <p>Note that the order of the specified proxy interfaces is
   299      * significant: two requests for a proxy class with the same combination
   300      * of interfaces but in a different order will result in two distinct
   301      * proxy classes.
   302      *
   303      * @param   loader the class loader to define the proxy class
   304      * @param   interfaces the list of interfaces for the proxy class
   305      *          to implement
   306      * @return  a proxy class that is defined in the specified class loader
   307      *          and that implements the specified interfaces
   308      * @throws  IllegalArgumentException if any of the restrictions on the
   309      *          parameters that may be passed to {@code getProxyClass}
   310      *          are violated
   311      * @throws  NullPointerException if the {@code interfaces} array
   312      *          argument or any of its elements are {@code null}
   313      */
   314     public static Class<?> getProxyClass(ClassLoader loader,
   315                                          Class<?>... interfaces)
   316         throws IllegalArgumentException
   317     {
   318         throw new IllegalArgumentException();
   319     }
   320 
   321     /**
   322      * Returns an instance of a proxy class for the specified interfaces
   323      * that dispatches method invocations to the specified invocation
   324      * handler.  This method is equivalent to:
   325      * <pre>
   326      *     Proxy.getProxyClass(loader, interfaces).
   327      *         getConstructor(new Class[] { InvocationHandler.class }).
   328      *         newInstance(new Object[] { handler });
   329      * </pre>
   330      *
   331      * <p>{@code Proxy.newProxyInstance} throws
   332      * {@code IllegalArgumentException} for the same reasons that
   333      * {@code Proxy.getProxyClass} does.
   334      *
   335      * @param   loader the class loader to define the proxy class
   336      * @param   interfaces the list of interfaces for the proxy class
   337      *          to implement
   338      * @param   h the invocation handler to dispatch method invocations to
   339      * @return  a proxy instance with the specified invocation handler of a
   340      *          proxy class that is defined by the specified class loader
   341      *          and that implements the specified interfaces
   342      * @throws  IllegalArgumentException if any of the restrictions on the
   343      *          parameters that may be passed to {@code getProxyClass}
   344      *          are violated
   345      * @throws  NullPointerException if the {@code interfaces} array
   346      *          argument or any of its elements are {@code null}, or
   347      *          if the invocation handler, {@code h}, is
   348      *          {@code null}
   349      */
   350     public static Object newProxyInstance(ClassLoader loader,
   351                                           Class<?>[] interfaces,
   352                                           InvocationHandler h)
   353         throws IllegalArgumentException
   354     {
   355         if (h == null) {
   356             throw new NullPointerException();
   357         }
   358         throw new IllegalArgumentException();
   359     }
   360 
   361     /**
   362      * Returns true if and only if the specified class was dynamically
   363      * generated to be a proxy class using the {@code getProxyClass}
   364      * method or the {@code newProxyInstance} method.
   365      *
   366      * <p>The reliability of this method is important for the ability
   367      * to use it to make security decisions, so its implementation should
   368      * not just test if the class in question extends {@code Proxy}.
   369      *
   370      * @param   cl the class to test
   371      * @return  {@code true} if the class is a proxy class and
   372      *          {@code false} otherwise
   373      * @throws  NullPointerException if {@code cl} is {@code null}
   374      */
   375     public static boolean isProxyClass(Class<?> cl) {
   376         if (cl == null) {
   377             throw new NullPointerException();
   378         }
   379 
   380         return false;
   381     }
   382 
   383     /**
   384      * Returns the invocation handler for the specified proxy instance.
   385      *
   386      * @param   proxy the proxy instance to return the invocation handler for
   387      * @return  the invocation handler for the proxy instance
   388      * @throws  IllegalArgumentException if the argument is not a
   389      *          proxy instance
   390      */
   391     public static InvocationHandler getInvocationHandler(Object proxy)
   392         throws IllegalArgumentException
   393     {
   394         /*
   395          * Verify that the object is actually a proxy instance.
   396          */
   397         if (!isProxyClass(proxy.getClass())) {
   398             throw new IllegalArgumentException("not a proxy instance");
   399         }
   400 
   401         Proxy p = (Proxy) proxy;
   402         return p.h;
   403     }
   404 
   405     private static native Class defineClass0(ClassLoader loader, String name,
   406                                              byte[] b, int off, int len);
   407 }