rt/emul/compact/src/main/java/java/lang/invoke/SerializedLambda.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 14 Sep 2014 19:27:44 +0200
changeset 1692 2f800fdc371e
permissions -rw-r--r--
Adding necessary fake classes to allow Javac to compile lamda expressions against our emulation library.
     1 /*
     2  * Copyright (c) 2012, 2013, 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 package java.lang.invoke;
    26 
    27 import java.io.Serializable;
    28 import java.lang.reflect.Method;
    29 import java.security.AccessController;
    30 import java.security.PrivilegedActionException;
    31 import java.security.PrivilegedExceptionAction;
    32 import java.util.Objects;
    33 
    34 /**
    35  * Serialized form of a lambda expression.  The properties of this class
    36  * represent the information that is present at the lambda factory site, including
    37  * static metafactory arguments such as the identity of the primary functional
    38  * interface method and the identity of the implementation method, as well as
    39  * dynamic metafactory arguments such as values captured from the lexical scope
    40  * at the time of lambda capture.
    41  *
    42  * <p>Implementors of serializable lambdas, such as compilers or language
    43  * runtime libraries, are expected to ensure that instances deserialize properly.
    44  * One means to do so is to ensure that the {@code writeReplace} method returns
    45  * an instance of {@code SerializedLambda}, rather than allowing default
    46  * serialization to proceed.
    47  *
    48  * <p>{@code SerializedLambda} has a {@code readResolve} method that looks for
    49  * a (possibly private) static method called
    50  * {@code $deserializeLambda$(SerializedLambda)} in the capturing class, invokes
    51  * that with itself as the first argument, and returns the result.  Lambda classes
    52  * implementing {@code $deserializeLambda$} are responsible for validating
    53  * that the properties of the {@code SerializedLambda} are consistent with a
    54  * lambda actually captured by that class.
    55  *
    56  * @see LambdaMetafactory
    57  */
    58 public final class SerializedLambda implements Serializable {
    59     private static final long serialVersionUID = 8025925345765570181L;
    60     private final Class<?> capturingClass;
    61     private final String functionalInterfaceClass;
    62     private final String functionalInterfaceMethodName;
    63     private final String functionalInterfaceMethodSignature;
    64     private final String implClass;
    65     private final String implMethodName;
    66     private final String implMethodSignature;
    67     private final int implMethodKind;
    68     private final String instantiatedMethodType;
    69     private final Object[] capturedArgs;
    70 
    71     /**
    72      * Create a {@code SerializedLambda} from the low-level information present
    73      * at the lambda factory site.
    74      *
    75      * @param capturingClass The class in which the lambda expression appears
    76      * @param functionalInterfaceClass Name, in slash-delimited form, of static
    77      *                                 type of the returned lambda object
    78      * @param functionalInterfaceMethodName Name of the functional interface
    79      *                                      method for the present at the
    80      *                                      lambda factory site
    81      * @param functionalInterfaceMethodSignature Signature of the functional
    82      *                                           interface method present at
    83      *                                           the lambda factory site
    84      * @param implMethodKind Method handle kind for the implementation method
    85      * @param implClass Name, in slash-delimited form, for the class holding
    86      *                  the implementation method
    87      * @param implMethodName Name of the implementation method
    88      * @param implMethodSignature Signature of the implementation method
    89      * @param instantiatedMethodType The signature of the primary functional
    90      *                               interface method after type variables
    91      *                               are substituted with their instantiation
    92      *                               from the capture site
    93      * @param capturedArgs The dynamic arguments to the lambda factory site,
    94      *                     which represent variables captured by
    95      *                     the lambda
    96      */
    97     public SerializedLambda(Class<?> capturingClass,
    98                             String functionalInterfaceClass,
    99                             String functionalInterfaceMethodName,
   100                             String functionalInterfaceMethodSignature,
   101                             int implMethodKind,
   102                             String implClass,
   103                             String implMethodName,
   104                             String implMethodSignature,
   105                             String instantiatedMethodType,
   106                             Object[] capturedArgs) {
   107         this.capturingClass = capturingClass;
   108         this.functionalInterfaceClass = functionalInterfaceClass;
   109         this.functionalInterfaceMethodName = functionalInterfaceMethodName;
   110         this.functionalInterfaceMethodSignature = functionalInterfaceMethodSignature;
   111         this.implMethodKind = implMethodKind;
   112         this.implClass = implClass;
   113         this.implMethodName = implMethodName;
   114         this.implMethodSignature = implMethodSignature;
   115         this.instantiatedMethodType = instantiatedMethodType;
   116         this.capturedArgs = Objects.requireNonNull(capturedArgs).clone();
   117     }
   118 
   119     /**
   120      * Get the name of the class that captured this lambda.
   121      * @return the name of the class that captured this lambda
   122      */
   123     public String getCapturingClass() {
   124         return capturingClass.getName().replace('.', '/');
   125     }
   126 
   127     /**
   128      * Get the name of the invoked type to which this
   129      * lambda has been converted
   130      * @return the name of the functional interface class to which
   131      * this lambda has been converted
   132      */
   133     public String getFunctionalInterfaceClass() {
   134         return functionalInterfaceClass;
   135     }
   136 
   137     /**
   138      * Get the name of the primary method for the functional interface
   139      * to which this lambda has been converted.
   140      * @return the name of the primary methods of the functional interface
   141      */
   142     public String getFunctionalInterfaceMethodName() {
   143         return functionalInterfaceMethodName;
   144     }
   145 
   146     /**
   147      * Get the signature of the primary method for the functional
   148      * interface to which this lambda has been converted.
   149      * @return the signature of the primary method of the functional
   150      * interface
   151      */
   152     public String getFunctionalInterfaceMethodSignature() {
   153         return functionalInterfaceMethodSignature;
   154     }
   155 
   156     /**
   157      * Get the name of the class containing the implementation
   158      * method.
   159      * @return the name of the class containing the implementation
   160      * method
   161      */
   162     public String getImplClass() {
   163         return implClass;
   164     }
   165 
   166     /**
   167      * Get the name of the implementation method.
   168      * @return the name of the implementation method
   169      */
   170     public String getImplMethodName() {
   171         return implMethodName;
   172     }
   173 
   174     /**
   175      * Get the signature of the implementation method.
   176      * @return the signature of the implementation method
   177      */
   178     public String getImplMethodSignature() {
   179         return implMethodSignature;
   180     }
   181 
   182     /**
   183      * Get the method handle kind (see {@link MethodHandleInfo}) of
   184      * the implementation method.
   185      * @return the method handle kind of the implementation method
   186      */
   187     public int getImplMethodKind() {
   188         return implMethodKind;
   189     }
   190 
   191     /**
   192      * Get the signature of the primary functional interface method
   193      * after type variables are substituted with their instantiation
   194      * from the capture site.
   195      * @return the signature of the primary functional interface method
   196      * after type variable processing
   197      */
   198     public final String getInstantiatedMethodType() {
   199         return instantiatedMethodType;
   200     }
   201 
   202     /**
   203      * Get the count of dynamic arguments to the lambda capture site.
   204      * @return the count of dynamic arguments to the lambda capture site
   205      */
   206     public int getCapturedArgCount() {
   207         return capturedArgs.length;
   208     }
   209 
   210     /**
   211      * Get a dynamic argument to the lambda capture site.
   212      * @param i the argument to capture
   213      * @return a dynamic argument to the lambda capture site
   214      */
   215     public Object getCapturedArg(int i) {
   216         return capturedArgs[i];
   217     }
   218 
   219     private Object readResolve() throws ReflectiveOperationException {
   220         try {
   221             Method deserialize = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
   222                 @Override
   223                 public Method run() throws Exception {
   224                     Method m = capturingClass.getDeclaredMethod("$deserializeLambda$", SerializedLambda.class);
   225                     m.setAccessible(true);
   226                     return m;
   227                 }
   228             });
   229 
   230             return deserialize.invoke(null, this);
   231         }
   232         catch (PrivilegedActionException e) {
   233             Exception cause = e.getException();
   234             if (cause instanceof ReflectiveOperationException)
   235                 throw (ReflectiveOperationException) cause;
   236             else if (cause instanceof RuntimeException)
   237                 throw (RuntimeException) cause;
   238             else
   239                 throw new RuntimeException("Exception in SerializedLambda.readResolve", e);
   240         }
   241     }
   242 
   243     @Override
   244     public String toString() {
   245         return String.format("SerializedLambda[%s=%s, %s=%s.%s:%s, " +
   246                              "%s=%s %s.%s:%s, %s=%s, %s=%d]",
   247                              "capturingClass", capturingClass,
   248                              "functionalInterfaceMethod", functionalInterfaceClass,
   249                                functionalInterfaceMethodName,
   250                                functionalInterfaceMethodSignature,
   251                              "implementation",
   252                                null,
   253                                implClass, implMethodName, implMethodSignature,
   254                              "instantiatedMethodType", instantiatedMethodType,
   255                              "numCaptured", capturedArgs.length);
   256     }
   257 }