jaroslav@1692: /* jaroslav@1692: * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. jaroslav@1692: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@1692: * jaroslav@1692: * This code is free software; you can redistribute it and/or modify it jaroslav@1692: * under the terms of the GNU General Public License version 2 only, as jaroslav@1692: * published by the Free Software Foundation. Oracle designates this jaroslav@1692: * particular file as subject to the "Classpath" exception as provided jaroslav@1692: * by Oracle in the LICENSE file that accompanied this code. jaroslav@1692: * jaroslav@1692: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@1692: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@1692: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@1692: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@1692: * accompanied this code). jaroslav@1692: * jaroslav@1692: * You should have received a copy of the GNU General Public License version jaroslav@1692: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@1692: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@1692: * jaroslav@1692: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@1692: * or visit www.oracle.com if you need additional information or have any jaroslav@1692: * questions. jaroslav@1692: */ jaroslav@1692: package java.lang.invoke; jaroslav@1692: jaroslav@1692: import java.io.Serializable; jaroslav@1692: import java.lang.reflect.Method; jaroslav@1692: import java.security.AccessController; jaroslav@1692: import java.security.PrivilegedActionException; jaroslav@1692: import java.security.PrivilegedExceptionAction; jaroslav@1692: import java.util.Objects; jaroslav@1692: jaroslav@1692: /** jaroslav@1692: * Serialized form of a lambda expression. The properties of this class jaroslav@1692: * represent the information that is present at the lambda factory site, including jaroslav@1692: * static metafactory arguments such as the identity of the primary functional jaroslav@1692: * interface method and the identity of the implementation method, as well as jaroslav@1692: * dynamic metafactory arguments such as values captured from the lexical scope jaroslav@1692: * at the time of lambda capture. jaroslav@1692: * jaroslav@1692: *
Implementors of serializable lambdas, such as compilers or language jaroslav@1692: * runtime libraries, are expected to ensure that instances deserialize properly. jaroslav@1692: * One means to do so is to ensure that the {@code writeReplace} method returns jaroslav@1692: * an instance of {@code SerializedLambda}, rather than allowing default jaroslav@1692: * serialization to proceed. jaroslav@1692: * jaroslav@1692: *
{@code SerializedLambda} has a {@code readResolve} method that looks for
jaroslav@1692: * a (possibly private) static method called
jaroslav@1692: * {@code $deserializeLambda$(SerializedLambda)} in the capturing class, invokes
jaroslav@1692: * that with itself as the first argument, and returns the result. Lambda classes
jaroslav@1692: * implementing {@code $deserializeLambda$} are responsible for validating
jaroslav@1692: * that the properties of the {@code SerializedLambda} are consistent with a
jaroslav@1692: * lambda actually captured by that class.
jaroslav@1692: *
jaroslav@1692: * @see LambdaMetafactory
jaroslav@1692: */
jaroslav@1692: public final class SerializedLambda implements Serializable {
jaroslav@1692: private static final long serialVersionUID = 8025925345765570181L;
jaroslav@1692: private final Class> capturingClass;
jaroslav@1692: private final String functionalInterfaceClass;
jaroslav@1692: private final String functionalInterfaceMethodName;
jaroslav@1692: private final String functionalInterfaceMethodSignature;
jaroslav@1692: private final String implClass;
jaroslav@1692: private final String implMethodName;
jaroslav@1692: private final String implMethodSignature;
jaroslav@1692: private final int implMethodKind;
jaroslav@1692: private final String instantiatedMethodType;
jaroslav@1692: private final Object[] capturedArgs;
jaroslav@1692:
jaroslav@1692: /**
jaroslav@1692: * Create a {@code SerializedLambda} from the low-level information present
jaroslav@1692: * at the lambda factory site.
jaroslav@1692: *
jaroslav@1692: * @param capturingClass The class in which the lambda expression appears
jaroslav@1692: * @param functionalInterfaceClass Name, in slash-delimited form, of static
jaroslav@1692: * type of the returned lambda object
jaroslav@1692: * @param functionalInterfaceMethodName Name of the functional interface
jaroslav@1692: * method for the present at the
jaroslav@1692: * lambda factory site
jaroslav@1692: * @param functionalInterfaceMethodSignature Signature of the functional
jaroslav@1692: * interface method present at
jaroslav@1692: * the lambda factory site
jaroslav@1692: * @param implMethodKind Method handle kind for the implementation method
jaroslav@1692: * @param implClass Name, in slash-delimited form, for the class holding
jaroslav@1692: * the implementation method
jaroslav@1692: * @param implMethodName Name of the implementation method
jaroslav@1692: * @param implMethodSignature Signature of the implementation method
jaroslav@1692: * @param instantiatedMethodType The signature of the primary functional
jaroslav@1692: * interface method after type variables
jaroslav@1692: * are substituted with their instantiation
jaroslav@1692: * from the capture site
jaroslav@1692: * @param capturedArgs The dynamic arguments to the lambda factory site,
jaroslav@1692: * which represent variables captured by
jaroslav@1692: * the lambda
jaroslav@1692: */
jaroslav@1692: public SerializedLambda(Class> capturingClass,
jaroslav@1692: String functionalInterfaceClass,
jaroslav@1692: String functionalInterfaceMethodName,
jaroslav@1692: String functionalInterfaceMethodSignature,
jaroslav@1692: int implMethodKind,
jaroslav@1692: String implClass,
jaroslav@1692: String implMethodName,
jaroslav@1692: String implMethodSignature,
jaroslav@1692: String instantiatedMethodType,
jaroslav@1692: Object[] capturedArgs) {
jaroslav@1692: this.capturingClass = capturingClass;
jaroslav@1692: this.functionalInterfaceClass = functionalInterfaceClass;
jaroslav@1692: this.functionalInterfaceMethodName = functionalInterfaceMethodName;
jaroslav@1692: this.functionalInterfaceMethodSignature = functionalInterfaceMethodSignature;
jaroslav@1692: this.implMethodKind = implMethodKind;
jaroslav@1692: this.implClass = implClass;
jaroslav@1692: this.implMethodName = implMethodName;
jaroslav@1692: this.implMethodSignature = implMethodSignature;
jaroslav@1692: this.instantiatedMethodType = instantiatedMethodType;
jaroslav@1692: this.capturedArgs = Objects.requireNonNull(capturedArgs).clone();
jaroslav@1692: }
jaroslav@1692:
jaroslav@1692: /**
jaroslav@1692: * Get the name of the class that captured this lambda.
jaroslav@1692: * @return the name of the class that captured this lambda
jaroslav@1692: */
jaroslav@1692: public String getCapturingClass() {
jaroslav@1692: return capturingClass.getName().replace('.', '/');
jaroslav@1692: }
jaroslav@1692:
jaroslav@1692: /**
jaroslav@1692: * Get the name of the invoked type to which this
jaroslav@1692: * lambda has been converted
jaroslav@1692: * @return the name of the functional interface class to which
jaroslav@1692: * this lambda has been converted
jaroslav@1692: */
jaroslav@1692: public String getFunctionalInterfaceClass() {
jaroslav@1692: return functionalInterfaceClass;
jaroslav@1692: }
jaroslav@1692:
jaroslav@1692: /**
jaroslav@1692: * Get the name of the primary method for the functional interface
jaroslav@1692: * to which this lambda has been converted.
jaroslav@1692: * @return the name of the primary methods of the functional interface
jaroslav@1692: */
jaroslav@1692: public String getFunctionalInterfaceMethodName() {
jaroslav@1692: return functionalInterfaceMethodName;
jaroslav@1692: }
jaroslav@1692:
jaroslav@1692: /**
jaroslav@1692: * Get the signature of the primary method for the functional
jaroslav@1692: * interface to which this lambda has been converted.
jaroslav@1692: * @return the signature of the primary method of the functional
jaroslav@1692: * interface
jaroslav@1692: */
jaroslav@1692: public String getFunctionalInterfaceMethodSignature() {
jaroslav@1692: return functionalInterfaceMethodSignature;
jaroslav@1692: }
jaroslav@1692:
jaroslav@1692: /**
jaroslav@1692: * Get the name of the class containing the implementation
jaroslav@1692: * method.
jaroslav@1692: * @return the name of the class containing the implementation
jaroslav@1692: * method
jaroslav@1692: */
jaroslav@1692: public String getImplClass() {
jaroslav@1692: return implClass;
jaroslav@1692: }
jaroslav@1692:
jaroslav@1692: /**
jaroslav@1692: * Get the name of the implementation method.
jaroslav@1692: * @return the name of the implementation method
jaroslav@1692: */
jaroslav@1692: public String getImplMethodName() {
jaroslav@1692: return implMethodName;
jaroslav@1692: }
jaroslav@1692:
jaroslav@1692: /**
jaroslav@1692: * Get the signature of the implementation method.
jaroslav@1692: * @return the signature of the implementation method
jaroslav@1692: */
jaroslav@1692: public String getImplMethodSignature() {
jaroslav@1692: return implMethodSignature;
jaroslav@1692: }
jaroslav@1692:
jaroslav@1692: /**
jaroslav@1692: * Get the method handle kind (see {@link MethodHandleInfo}) of
jaroslav@1692: * the implementation method.
jaroslav@1692: * @return the method handle kind of the implementation method
jaroslav@1692: */
jaroslav@1692: public int getImplMethodKind() {
jaroslav@1692: return implMethodKind;
jaroslav@1692: }
jaroslav@1692:
jaroslav@1692: /**
jaroslav@1692: * Get the signature of the primary functional interface method
jaroslav@1692: * after type variables are substituted with their instantiation
jaroslav@1692: * from the capture site.
jaroslav@1692: * @return the signature of the primary functional interface method
jaroslav@1692: * after type variable processing
jaroslav@1692: */
jaroslav@1692: public final String getInstantiatedMethodType() {
jaroslav@1692: return instantiatedMethodType;
jaroslav@1692: }
jaroslav@1692:
jaroslav@1692: /**
jaroslav@1692: * Get the count of dynamic arguments to the lambda capture site.
jaroslav@1692: * @return the count of dynamic arguments to the lambda capture site
jaroslav@1692: */
jaroslav@1692: public int getCapturedArgCount() {
jaroslav@1692: return capturedArgs.length;
jaroslav@1692: }
jaroslav@1692:
jaroslav@1692: /**
jaroslav@1692: * Get a dynamic argument to the lambda capture site.
jaroslav@1692: * @param i the argument to capture
jaroslav@1692: * @return a dynamic argument to the lambda capture site
jaroslav@1692: */
jaroslav@1692: public Object getCapturedArg(int i) {
jaroslav@1692: return capturedArgs[i];
jaroslav@1692: }
jaroslav@1692:
jaroslav@1692: private Object readResolve() throws ReflectiveOperationException {
jaroslav@1692: try {
jaroslav@1692: Method deserialize = AccessController.doPrivileged(new PrivilegedExceptionAction