1 /* 2 * Copyright (c) 2012, 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 represent the information that is present 36 * at the lambda factory site, including the identity of the primary functional interface method, the identity of the 37 * implementation method, and any variables captured from the local environment at the time of lambda capture. 38 * 39 * @see LambdaMetafactory 40 */ 41 public final class SerializedLambda implements Serializable { 42 private static final long serialVersionUID = 8025925345765570181L; 43 private final Class<?> capturingClass; 44 private final String functionalInterfaceClass; 45 private final String functionalInterfaceMethodName; 46 private final String functionalInterfaceMethodSignature; 47 private final int functionalInterfaceMethodKind; 48 private final String implClass; 49 private final String implMethodName; 50 private final String implMethodSignature; 51 private final int implMethodKind; 52 private final String instantiatedMethodType; 53 private final Object[] capturedArgs; 54 55 /** 56 * Create a {@code SerializedLambda} from the low-level information present at the lambda factory site. 57 * 58 * @param capturingClass The class in which the lambda expression appears 59 * @param functionalInterfaceMethodKind Method handle kind (see {@link MethodHandleInfo}) for the 60 * functional interface method handle present at the lambda factory site 61 * @param functionalInterfaceClass Name, in slash-delimited form, for the functional interface class present at the 62 * lambda factory site 63 * @param functionalInterfaceMethodName Name of the primary method for the functional interface present at the 64 * lambda factory site 65 * @param functionalInterfaceMethodSignature Signature of the primary method for the functional interface present 66 * at the lambda factory site 67 * @param implMethodKind Method handle kind for the implementation method 68 * @param implClass Name, in slash-delimited form, for the class holding the implementation method 69 * @param implMethodName Name of the implementation method 70 * @param implMethodSignature Signature of the implementation method 71 * @param instantiatedMethodType The signature of the primary functional interface method after type variables 72 * are substituted with their instantiation from the capture site 73 * @param capturedArgs The dynamic arguments to the lambda factory site, which represent variables captured by 74 * the lambda 75 */ 76 public SerializedLambda(Class<?> capturingClass, 77 int functionalInterfaceMethodKind, 78 String functionalInterfaceClass, 79 String functionalInterfaceMethodName, 80 String functionalInterfaceMethodSignature, 81 int implMethodKind, 82 String implClass, 83 String implMethodName, 84 String implMethodSignature, 85 String instantiatedMethodType, 86 Object[] capturedArgs) { 87 this.capturingClass = capturingClass; 88 this.functionalInterfaceMethodKind = functionalInterfaceMethodKind; 89 this.functionalInterfaceClass = functionalInterfaceClass; 90 this.functionalInterfaceMethodName = functionalInterfaceMethodName; 91 this.functionalInterfaceMethodSignature = functionalInterfaceMethodSignature; 92 this.implMethodKind = implMethodKind; 93 this.implClass = implClass; 94 this.implMethodName = implMethodName; 95 this.implMethodSignature = implMethodSignature; 96 this.instantiatedMethodType = instantiatedMethodType; 97 this.capturedArgs = Objects.requireNonNull(capturedArgs).clone(); 98 } 99 100 /** Get the name of the class that captured this lambda */ 101 public String getCapturingClass() { 102 return capturingClass.getName().replace('.', '/'); 103 } 104 105 /** Get the name of the functional interface class to which this lambda has been converted */ 106 public String getFunctionalInterfaceClass() { 107 return functionalInterfaceClass; 108 } 109 110 /** Get the name of the primary method for the functional interface to which this lambda has been converted */ 111 public String getFunctionalInterfaceMethodName() { 112 return functionalInterfaceMethodName; 113 } 114 115 /** Get the signature of the primary method for the functional interface to which this lambda has been converted */ 116 public String getFunctionalInterfaceMethodSignature() { 117 return functionalInterfaceMethodSignature; 118 } 119 120 /** Get the method handle kind (see {@link MethodHandleInfo}) of the primary method for the functional interface 121 * to which this lambda has been converted */ 122 public int getFunctionalInterfaceMethodKind() { 123 return functionalInterfaceMethodKind; 124 } 125 126 /** Get the name of the class containing the implementation method */ 127 public String getImplClass() { 128 return implClass; 129 } 130 131 /** Get the name of the implementation method */ 132 public String getImplMethodName() { 133 return implMethodName; 134 } 135 136 /** Get the signature of the implementation method */ 137 public String getImplMethodSignature() { 138 return implMethodSignature; 139 } 140 141 /** Get the method handle kind (see {@link MethodHandleInfo}) of the implementation method */ 142 public int getImplMethodKind() { 143 return implMethodKind; 144 } 145 146 /** 147 * Get the signature of the primary functional interface method after type variables are substituted with 148 * their instantiation from the capture site 149 */ 150 public final String getInstantiatedMethodType() { 151 return instantiatedMethodType; 152 } 153 154 /** Get the count of dynamic arguments to the lambda capture site */ 155 public int getCapturedArgCount() { 156 return capturedArgs.length; 157 } 158 159 /** Get a dynamic argument to the lambda capture site */ 160 public Object getCapturedArg(int i) { 161 return capturedArgs[i]; 162 } 163 164 private Object readResolve() throws ReflectiveOperationException { 165 try { 166 Method deserialize = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() { 167 @Override 168 public Method run() throws Exception { 169 Method m = capturingClass.getDeclaredMethod("$deserializeLambda$", SerializedLambda.class); 170 m.setAccessible(true); 171 return m; 172 } 173 }); 174 175 return deserialize.invoke(null, this); 176 } 177 catch (PrivilegedActionException e) { 178 Exception cause = e.getException(); 179 if (cause instanceof ReflectiveOperationException) 180 throw (ReflectiveOperationException) cause; 181 else if (cause instanceof RuntimeException) 182 throw (RuntimeException) cause; 183 else 184 throw new RuntimeException("Exception in SerializedLambda.readResolve", e); 185 } 186 } 187 188 @Override 189 public String toString() { 190 return String.format("SerializedLambda[capturingClass=%s, functionalInterfaceMethod=%s %s.%s:%s, " + 191 "implementation=%s %s.%s:%s, instantiatedMethodType=%s, numCaptured=%d]", 192 capturingClass, MethodHandleInfo.getReferenceKindString(functionalInterfaceMethodKind), 193 functionalInterfaceClass, functionalInterfaceMethodName, functionalInterfaceMethodSignature, 194 MethodHandleInfo.getReferenceKindString(implMethodKind), implClass, implMethodName, 195 implMethodSignature, instantiatedMethodType, capturedArgs.length); 196 } 197 }