rt/emul/compact/src/main/java/java/lang/invoke/InnerClassLambdaMetafactory.java
branchjdk8
changeset 1653 bd151459ee4f
parent 1652 8fb89a569621
child 1654 da24a2411ee7
     1.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/InnerClassLambdaMetafactory.java	Sun Aug 10 06:21:50 2014 +0200
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,551 +0,0 @@
     1.4 -/*
     1.5 - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 - *
     1.8 - * This code is free software; you can redistribute it and/or modify it
     1.9 - * under the terms of the GNU General Public License version 2 only, as
    1.10 - * published by the Free Software Foundation.  Oracle designates this
    1.11 - * particular file as subject to the "Classpath" exception as provided
    1.12 - * by Oracle in the LICENSE file that accompanied this code.
    1.13 - *
    1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 - * version 2 for more details (a copy is included in the LICENSE file that
    1.18 - * accompanied this code).
    1.19 - *
    1.20 - * You should have received a copy of the GNU General Public License version
    1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 - *
    1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 - * or visit www.oracle.com if you need additional information or have any
    1.26 - * questions.
    1.27 - */
    1.28 -
    1.29 -package java.lang.invoke;
    1.30 -
    1.31 -import jdk.internal.org.objectweb.asm.*;
    1.32 -import sun.invoke.util.BytecodeDescriptor;
    1.33 -import sun.misc.Unsafe;
    1.34 -import sun.security.action.GetPropertyAction;
    1.35 -
    1.36 -import java.io.FilePermission;
    1.37 -import java.io.Serializable;
    1.38 -import java.lang.reflect.Constructor;
    1.39 -import java.security.AccessController;
    1.40 -import java.security.PrivilegedAction;
    1.41 -import java.util.LinkedHashSet;
    1.42 -import java.util.concurrent.atomic.AtomicInteger;
    1.43 -import java.util.PropertyPermission;
    1.44 -import java.util.Set;
    1.45 -
    1.46 -import static jdk.internal.org.objectweb.asm.Opcodes.*;
    1.47 -
    1.48 -/**
    1.49 - * Lambda metafactory implementation which dynamically creates an
    1.50 - * inner-class-like class per lambda callsite.
    1.51 - *
    1.52 - * @see LambdaMetafactory
    1.53 - */
    1.54 -/* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
    1.55 -    private static final Unsafe UNSAFE = Unsafe.getUnsafe();
    1.56 -
    1.57 -    private static final int CLASSFILE_VERSION = 52;
    1.58 -    private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
    1.59 -    private static final String JAVA_LANG_OBJECT = "java/lang/Object";
    1.60 -    private static final String NAME_CTOR = "<init>";
    1.61 -    private static final String NAME_FACTORY = "get$Lambda";
    1.62 -
    1.63 -    //Serialization support
    1.64 -    private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
    1.65 -    private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException";
    1.66 -    private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
    1.67 -    private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V";
    1.68 -    private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V";
    1.69 -    private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
    1.70 -    private static final String NAME_METHOD_READ_OBJECT = "readObject";
    1.71 -    private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
    1.72 -    private static final String DESCR_CTOR_SERIALIZED_LAMBDA
    1.73 -            = MethodType.methodType(void.class,
    1.74 -                                    Class.class,
    1.75 -                                    String.class, String.class, String.class,
    1.76 -                                    int.class, String.class, String.class, String.class,
    1.77 -                                    String.class,
    1.78 -                                    Object[].class).toMethodDescriptorString();
    1.79 -    private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION
    1.80 -            = MethodType.methodType(void.class, String.class).toMethodDescriptorString();
    1.81 -    private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION};
    1.82 -
    1.83 -
    1.84 -    private static final String[] EMPTY_STRING_ARRAY = new String[0];
    1.85 -
    1.86 -    // Used to ensure that each spun class name is unique
    1.87 -    private static final AtomicInteger counter = new AtomicInteger(0);
    1.88 -
    1.89 -
    1.90 -    // See context values in AbstractValidatingLambdaMetafactory
    1.91 -    private final String implMethodClassName;        // Name of type containing implementation "CC"
    1.92 -    private final String implMethodName;             // Name of implementation method "impl"
    1.93 -    private final String implMethodDesc;             // Type descriptor for implementation methods "(I)Ljava/lang/String;"
    1.94 -    private final Class<?> implMethodReturnClass;    // class for implementaion method return type "Ljava/lang/String;"
    1.95 -    private final MethodType constructorType;        // Generated class constructor type "(CC)void"
    1.96 -    private final ClassWriter cw;                    // ASM class writer
    1.97 -    private final String[] argNames;                 // Generated names for the constructor arguments
    1.98 -    private final String[] argDescs;                 // Type descriptors for the constructor arguments
    1.99 -    private final String lambdaClassName;            // Generated name for the generated class "X$$Lambda$1"
   1.100 -
   1.101 -    /**
   1.102 -     * General meta-factory constructor, supporting both standard cases and
   1.103 -     * allowing for uncommon options such as serialization or bridging.
   1.104 -     *
   1.105 -     * @param caller Stacked automatically by VM; represents a lookup context
   1.106 -     *               with the accessibility privileges of the caller.
   1.107 -     * @param invokedType Stacked automatically by VM; the signature of the
   1.108 -     *                    invoked method, which includes the expected static
   1.109 -     *                    type of the returned lambda object, and the static
   1.110 -     *                    types of the captured arguments for the lambda.  In
   1.111 -     *                    the event that the implementation method is an
   1.112 -     *                    instance method, the first argument in the invocation
   1.113 -     *                    signature will correspond to the receiver.
   1.114 -     * @param samMethodName Name of the method in the functional interface to
   1.115 -     *                      which the lambda or method reference is being
   1.116 -     *                      converted, represented as a String.
   1.117 -     * @param samMethodType Type of the method in the functional interface to
   1.118 -     *                      which the lambda or method reference is being
   1.119 -     *                      converted, represented as a MethodType.
   1.120 -     * @param implMethod The implementation method which should be called (with
   1.121 -     *                   suitable adaptation of argument types, return types,
   1.122 -     *                   and adjustment for captured arguments) when methods of
   1.123 -     *                   the resulting functional interface instance are invoked.
   1.124 -     * @param instantiatedMethodType The signature of the primary functional
   1.125 -     *                               interface method after type variables are
   1.126 -     *                               substituted with their instantiation from
   1.127 -     *                               the capture site
   1.128 -     * @param isSerializable Should the lambda be made serializable?  If set,
   1.129 -     *                       either the target type or one of the additional SAM
   1.130 -     *                       types must extend {@code Serializable}.
   1.131 -     * @param markerInterfaces Additional interfaces which the lambda object
   1.132 -     *                       should implement.
   1.133 -     * @param additionalBridges Method types for additional signatures to be
   1.134 -     *                          bridged to the implementation method
   1.135 -     * @throws LambdaConversionException If any of the meta-factory protocol
   1.136 -     * invariants are violated
   1.137 -     */
   1.138 -    public InnerClassLambdaMetafactory(MethodHandles.Lookup caller,
   1.139 -                                       MethodType invokedType,
   1.140 -                                       String samMethodName,
   1.141 -                                       MethodType samMethodType,
   1.142 -                                       MethodHandle implMethod,
   1.143 -                                       MethodType instantiatedMethodType,
   1.144 -                                       boolean isSerializable,
   1.145 -                                       Class<?>[] markerInterfaces,
   1.146 -                                       MethodType[] additionalBridges)
   1.147 -            throws LambdaConversionException {
   1.148 -        super(caller, invokedType, samMethodName, samMethodType,
   1.149 -              implMethod, instantiatedMethodType,
   1.150 -              isSerializable, markerInterfaces, additionalBridges);
   1.151 -        implMethodClassName = implDefiningClass.getName().replace('.', '/');
   1.152 -        implMethodName = implInfo.getName();
   1.153 -        implMethodDesc = implMethodType.toMethodDescriptorString();
   1.154 -        implMethodReturnClass = (implKind == MethodHandleInfo.REF_newInvokeSpecial)
   1.155 -                ? implDefiningClass
   1.156 -                : implMethodType.returnType();
   1.157 -        constructorType = invokedType.changeReturnType(Void.TYPE);
   1.158 -        lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet();
   1.159 -        cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
   1.160 -        int parameterCount = invokedType.parameterCount();
   1.161 -        if (parameterCount > 0) {
   1.162 -            argNames = new String[parameterCount];
   1.163 -            argDescs = new String[parameterCount];
   1.164 -            for (int i = 0; i < parameterCount; i++) {
   1.165 -                argNames[i] = "arg$" + (i + 1);
   1.166 -                argDescs[i] = BytecodeDescriptor.unparse(invokedType.parameterType(i));
   1.167 -            }
   1.168 -        } else {
   1.169 -            argNames = argDescs = EMPTY_STRING_ARRAY;
   1.170 -        }
   1.171 -    }
   1.172 -
   1.173 -    /**
   1.174 -     * Build the CallSite. Generate a class file which implements the functional
   1.175 -     * interface, define the class, if there are no parameters create an instance
   1.176 -     * of the class which the CallSite will return, otherwise, generate handles
   1.177 -     * which will call the class' constructor.
   1.178 -     *
   1.179 -     * @return a CallSite, which, when invoked, will return an instance of the
   1.180 -     * functional interface
   1.181 -     * @throws ReflectiveOperationException
   1.182 -     * @throws LambdaConversionException If properly formed functional interface
   1.183 -     * is not found
   1.184 -     */
   1.185 -    @Override
   1.186 -    CallSite buildCallSite() throws LambdaConversionException {
   1.187 -        final Class<?> innerClass = spinInnerClass();
   1.188 -        if (invokedType.parameterCount() == 0) {
   1.189 -            final Constructor[] ctrs = AccessController.doPrivileged(
   1.190 -                    new PrivilegedAction<Constructor[]>() {
   1.191 -                @Override
   1.192 -                public Constructor[] run() {
   1.193 -                    Constructor<?>[] ctrs = innerClass.getDeclaredConstructors();
   1.194 -                    if (ctrs.length == 1) {
   1.195 -                        // The lambda implementing inner class constructor is private, set
   1.196 -                        // it accessible (by us) before creating the constant sole instance
   1.197 -                        ctrs[0].setAccessible(true);
   1.198 -                    }
   1.199 -                    return ctrs;
   1.200 -                }
   1.201 -                    });
   1.202 -            if (ctrs.length != 1) {
   1.203 -                throw new LambdaConversionException("Expected one lambda constructor for "
   1.204 -                        + innerClass.getCanonicalName() + ", got " + ctrs.length);
   1.205 -            }
   1.206 -
   1.207 -            try {
   1.208 -                Object inst = ctrs[0].newInstance();
   1.209 -                return new ConstantCallSite(MethodHandles.constant(samBase, inst));
   1.210 -            }
   1.211 -            catch (ReflectiveOperationException e) {
   1.212 -                throw new LambdaConversionException("Exception instantiating lambda object", e);
   1.213 -            }
   1.214 -        } else {
   1.215 -            try {
   1.216 -                UNSAFE.ensureClassInitialized(innerClass);
   1.217 -                return new ConstantCallSite(
   1.218 -                        MethodHandles.Lookup.IMPL_LOOKUP
   1.219 -                             .findStatic(innerClass, NAME_FACTORY, invokedType));
   1.220 -            }
   1.221 -            catch (ReflectiveOperationException e) {
   1.222 -                throw new LambdaConversionException("Exception finding constructor", e);
   1.223 -            }
   1.224 -        }
   1.225 -    }
   1.226 -
   1.227 -    /**
   1.228 -     * Generate a class file which implements the functional
   1.229 -     * interface, define and return the class.
   1.230 -     *
   1.231 -     * @implNote The class that is generated does not include signature
   1.232 -     * information for exceptions that may be present on the SAM method.
   1.233 -     * This is to reduce classfile size, and is harmless as checked exceptions
   1.234 -     * are erased anyway, no one will ever compile against this classfile,
   1.235 -     * and we make no guarantees about the reflective properties of lambda
   1.236 -     * objects.
   1.237 -     *
   1.238 -     * @return a Class which implements the functional interface
   1.239 -     * @throws LambdaConversionException If properly formed functional interface
   1.240 -     * is not found
   1.241 -     */
   1.242 -    private Class<?> spinInnerClass() throws LambdaConversionException {
   1.243 -        String[] interfaces;
   1.244 -        String samIntf = samBase.getName().replace('.', '/');
   1.245 -        boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase);
   1.246 -        if (markerInterfaces.length == 0) {
   1.247 -            interfaces = new String[]{samIntf};
   1.248 -        } else {
   1.249 -            // Assure no duplicate interfaces (ClassFormatError)
   1.250 -            Set<String> itfs = new LinkedHashSet<>(markerInterfaces.length + 1);
   1.251 -            itfs.add(samIntf);
   1.252 -            for (Class<?> markerInterface : markerInterfaces) {
   1.253 -                itfs.add(markerInterface.getName().replace('.', '/'));
   1.254 -                accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(markerInterface);
   1.255 -            }
   1.256 -            interfaces = itfs.toArray(new String[itfs.size()]);
   1.257 -        }
   1.258 -
   1.259 -        cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
   1.260 -                 lambdaClassName, null,
   1.261 -                 JAVA_LANG_OBJECT, interfaces);
   1.262 -
   1.263 -        // Generate final fields to be filled in by constructor
   1.264 -        for (int i = 0; i < argDescs.length; i++) {
   1.265 -            FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL,
   1.266 -                                            argNames[i],
   1.267 -                                            argDescs[i],
   1.268 -                                            null, null);
   1.269 -            fv.visitEnd();
   1.270 -        }
   1.271 -
   1.272 -        generateConstructor();
   1.273 -
   1.274 -        if (invokedType.parameterCount() != 0) {
   1.275 -            generateFactory();
   1.276 -        }
   1.277 -
   1.278 -        // Forward the SAM method
   1.279 -        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
   1.280 -                                          samMethodType.toMethodDescriptorString(), null, null);
   1.281 -        new ForwardingMethodGenerator(mv).generate(samMethodType);
   1.282 -
   1.283 -        // Forward the bridges
   1.284 -        if (additionalBridges != null) {
   1.285 -            for (MethodType mt : additionalBridges) {
   1.286 -                mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName,
   1.287 -                                    mt.toMethodDescriptorString(), null, null);
   1.288 -                new ForwardingMethodGenerator(mv).generate(mt);
   1.289 -            }
   1.290 -        }
   1.291 -
   1.292 -        if (isSerializable)
   1.293 -            generateSerializationFriendlyMethods();
   1.294 -        else if (accidentallySerializable)
   1.295 -            generateSerializationHostileMethods();
   1.296 -
   1.297 -        cw.visitEnd();
   1.298 -
   1.299 -        // Define the generated class in this VM.
   1.300 -
   1.301 -        final byte[] classBytes = cw.toByteArray();
   1.302 -
   1.303 -        // If requested, dump out to a file for debugging purposes
   1.304 -        if (dumper != null) {
   1.305 -            AccessController.doPrivileged(new PrivilegedAction<Void>() {
   1.306 -                @Override
   1.307 -                public Void run() {
   1.308 -                    dumper.dumpClass(lambdaClassName, classBytes);
   1.309 -                    return null;
   1.310 -                }
   1.311 -            }, null,
   1.312 -            new FilePermission("<<ALL FILES>>", "read, write"),
   1.313 -            // createDirectories may need it
   1.314 -            new PropertyPermission("user.dir", "read"));
   1.315 -        }
   1.316 -
   1.317 -        return UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
   1.318 -    }
   1.319 -
   1.320 -    /**
   1.321 -     * Generate the factory method for the class
   1.322 -     */
   1.323 -    private void generateFactory() {
   1.324 -        MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null);
   1.325 -        m.visitCode();
   1.326 -        m.visitTypeInsn(NEW, lambdaClassName);
   1.327 -        m.visitInsn(Opcodes.DUP);
   1.328 -        int parameterCount = invokedType.parameterCount();
   1.329 -        for (int typeIndex = 0, varIndex = 0; typeIndex < parameterCount; typeIndex++) {
   1.330 -            Class<?> argType = invokedType.parameterType(typeIndex);
   1.331 -            m.visitVarInsn(getLoadOpcode(argType), varIndex);
   1.332 -            varIndex += getParameterSize(argType);
   1.333 -        }
   1.334 -        m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString());
   1.335 -        m.visitInsn(ARETURN);
   1.336 -        m.visitMaxs(-1, -1);
   1.337 -        m.visitEnd();
   1.338 -    }
   1.339 -
   1.340 -    /**
   1.341 -     * Generate the constructor for the class
   1.342 -     */
   1.343 -    private void generateConstructor() {
   1.344 -        // Generate constructor
   1.345 -        MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR,
   1.346 -                                            constructorType.toMethodDescriptorString(), null, null);
   1.347 -        ctor.visitCode();
   1.348 -        ctor.visitVarInsn(ALOAD, 0);
   1.349 -        ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR,
   1.350 -                             METHOD_DESCRIPTOR_VOID);
   1.351 -        int parameterCount = invokedType.parameterCount();
   1.352 -        for (int i = 0, lvIndex = 0; i < parameterCount; i++) {
   1.353 -            ctor.visitVarInsn(ALOAD, 0);
   1.354 -            Class<?> argType = invokedType.parameterType(i);
   1.355 -            ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
   1.356 -            lvIndex += getParameterSize(argType);
   1.357 -            ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]);
   1.358 -        }
   1.359 -        ctor.visitInsn(RETURN);
   1.360 -        // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
   1.361 -        ctor.visitMaxs(-1, -1);
   1.362 -        ctor.visitEnd();
   1.363 -    }
   1.364 -
   1.365 -    /**
   1.366 -     * Generate a writeReplace method that supports serialization
   1.367 -     */
   1.368 -    private void generateSerializationFriendlyMethods() {
   1.369 -        TypeConvertingMethodAdapter mv
   1.370 -                = new TypeConvertingMethodAdapter(
   1.371 -                    cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
   1.372 -                    NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE,
   1.373 -                    null, null));
   1.374 -
   1.375 -        mv.visitCode();
   1.376 -        mv.visitTypeInsn(NEW, NAME_SERIALIZED_LAMBDA);
   1.377 -        mv.visitInsn(DUP);
   1.378 -        mv.visitLdcInsn(Type.getType(targetClass));
   1.379 -        mv.visitLdcInsn(invokedType.returnType().getName().replace('.', '/'));
   1.380 -        mv.visitLdcInsn(samMethodName);
   1.381 -        mv.visitLdcInsn(samMethodType.toMethodDescriptorString());
   1.382 -        mv.visitLdcInsn(implInfo.getReferenceKind());
   1.383 -        mv.visitLdcInsn(implInfo.getDeclaringClass().getName().replace('.', '/'));
   1.384 -        mv.visitLdcInsn(implInfo.getName());
   1.385 -        mv.visitLdcInsn(implInfo.getMethodType().toMethodDescriptorString());
   1.386 -        mv.visitLdcInsn(instantiatedMethodType.toMethodDescriptorString());
   1.387 -        mv.iconst(argDescs.length);
   1.388 -        mv.visitTypeInsn(ANEWARRAY, JAVA_LANG_OBJECT);
   1.389 -        for (int i = 0; i < argDescs.length; i++) {
   1.390 -            mv.visitInsn(DUP);
   1.391 -            mv.iconst(i);
   1.392 -            mv.visitVarInsn(ALOAD, 0);
   1.393 -            mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
   1.394 -            mv.boxIfTypePrimitive(Type.getType(argDescs[i]));
   1.395 -            mv.visitInsn(AASTORE);
   1.396 -        }
   1.397 -        mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR,
   1.398 -                DESCR_CTOR_SERIALIZED_LAMBDA);
   1.399 -        mv.visitInsn(ARETURN);
   1.400 -        // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
   1.401 -        mv.visitMaxs(-1, -1);
   1.402 -        mv.visitEnd();
   1.403 -    }
   1.404 -
   1.405 -    /**
   1.406 -     * Generate a readObject/writeObject method that is hostile to serialization
   1.407 -     */
   1.408 -    private void generateSerializationHostileMethods() {
   1.409 -        MethodVisitor mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
   1.410 -                                          NAME_METHOD_WRITE_OBJECT, DESCR_METHOD_WRITE_OBJECT,
   1.411 -                                          null, SER_HOSTILE_EXCEPTIONS);
   1.412 -        mv.visitCode();
   1.413 -        mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION);
   1.414 -        mv.visitInsn(DUP);
   1.415 -        mv.visitLdcInsn("Non-serializable lambda");
   1.416 -        mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
   1.417 -                           DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION);
   1.418 -        mv.visitInsn(ATHROW);
   1.419 -        mv.visitMaxs(-1, -1);
   1.420 -        mv.visitEnd();
   1.421 -
   1.422 -        mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
   1.423 -                            NAME_METHOD_READ_OBJECT, DESCR_METHOD_READ_OBJECT,
   1.424 -                            null, SER_HOSTILE_EXCEPTIONS);
   1.425 -        mv.visitCode();
   1.426 -        mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION);
   1.427 -        mv.visitInsn(DUP);
   1.428 -        mv.visitLdcInsn("Non-serializable lambda");
   1.429 -        mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
   1.430 -                           DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION);
   1.431 -        mv.visitInsn(ATHROW);
   1.432 -        mv.visitMaxs(-1, -1);
   1.433 -        mv.visitEnd();
   1.434 -    }
   1.435 -
   1.436 -    /**
   1.437 -     * This class generates a method body which calls the lambda implementation
   1.438 -     * method, converting arguments, as needed.
   1.439 -     */
   1.440 -    private class ForwardingMethodGenerator extends TypeConvertingMethodAdapter {
   1.441 -
   1.442 -        ForwardingMethodGenerator(MethodVisitor mv) {
   1.443 -            super(mv);
   1.444 -        }
   1.445 -
   1.446 -        void generate(MethodType methodType) {
   1.447 -            visitCode();
   1.448 -
   1.449 -            if (implKind == MethodHandleInfo.REF_newInvokeSpecial) {
   1.450 -                visitTypeInsn(NEW, implMethodClassName);
   1.451 -                visitInsn(DUP);
   1.452 -            }
   1.453 -            for (int i = 0; i < argNames.length; i++) {
   1.454 -                visitVarInsn(ALOAD, 0);
   1.455 -                visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
   1.456 -            }
   1.457 -
   1.458 -            convertArgumentTypes(methodType);
   1.459 -
   1.460 -            // Invoke the method we want to forward to
   1.461 -            visitMethodInsn(invocationOpcode(), implMethodClassName,
   1.462 -                            implMethodName, implMethodDesc,
   1.463 -                            implDefiningClass.isInterface());
   1.464 -
   1.465 -            // Convert the return value (if any) and return it
   1.466 -            // Note: if adapting from non-void to void, the 'return'
   1.467 -            // instruction will pop the unneeded result
   1.468 -            Class<?> samReturnClass = methodType.returnType();
   1.469 -            convertType(implMethodReturnClass, samReturnClass, samReturnClass);
   1.470 -            visitInsn(getReturnOpcode(samReturnClass));
   1.471 -            // Maxs computed by ClassWriter.COMPUTE_MAXS,these arguments ignored
   1.472 -            visitMaxs(-1, -1);
   1.473 -            visitEnd();
   1.474 -        }
   1.475 -
   1.476 -        private void convertArgumentTypes(MethodType samType) {
   1.477 -            int lvIndex = 0;
   1.478 -            boolean samIncludesReceiver = implIsInstanceMethod &&
   1.479 -                                                   invokedType.parameterCount() == 0;
   1.480 -            int samReceiverLength = samIncludesReceiver ? 1 : 0;
   1.481 -            if (samIncludesReceiver) {
   1.482 -                // push receiver
   1.483 -                Class<?> rcvrType = samType.parameterType(0);
   1.484 -                visitVarInsn(getLoadOpcode(rcvrType), lvIndex + 1);
   1.485 -                lvIndex += getParameterSize(rcvrType);
   1.486 -                convertType(rcvrType, implDefiningClass, instantiatedMethodType.parameterType(0));
   1.487 -            }
   1.488 -            int samParametersLength = samType.parameterCount();
   1.489 -            int argOffset = implMethodType.parameterCount() - samParametersLength;
   1.490 -            for (int i = samReceiverLength; i < samParametersLength; i++) {
   1.491 -                Class<?> argType = samType.parameterType(i);
   1.492 -                visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
   1.493 -                lvIndex += getParameterSize(argType);
   1.494 -                convertType(argType, implMethodType.parameterType(argOffset + i), instantiatedMethodType.parameterType(i));
   1.495 -            }
   1.496 -        }
   1.497 -
   1.498 -        private int invocationOpcode() throws InternalError {
   1.499 -            switch (implKind) {
   1.500 -                case MethodHandleInfo.REF_invokeStatic:
   1.501 -                    return INVOKESTATIC;
   1.502 -                case MethodHandleInfo.REF_newInvokeSpecial:
   1.503 -                    return INVOKESPECIAL;
   1.504 -                 case MethodHandleInfo.REF_invokeVirtual:
   1.505 -                    return INVOKEVIRTUAL;
   1.506 -                case MethodHandleInfo.REF_invokeInterface:
   1.507 -                    return INVOKEINTERFACE;
   1.508 -                case MethodHandleInfo.REF_invokeSpecial:
   1.509 -                    return INVOKESPECIAL;
   1.510 -                default:
   1.511 -                    throw new InternalError("Unexpected invocation kind: " + implKind);
   1.512 -            }
   1.513 -        }
   1.514 -    }
   1.515 -
   1.516 -    static int getParameterSize(Class<?> c) {
   1.517 -        if (c == Void.TYPE) {
   1.518 -            return 0;
   1.519 -        } else if (c == Long.TYPE || c == Double.TYPE) {
   1.520 -            return 2;
   1.521 -        }
   1.522 -        return 1;
   1.523 -    }
   1.524 -
   1.525 -    static int getLoadOpcode(Class<?> c) {
   1.526 -        if(c == Void.TYPE) {
   1.527 -            throw new InternalError("Unexpected void type of load opcode");
   1.528 -        }
   1.529 -        return ILOAD + getOpcodeOffset(c);
   1.530 -    }
   1.531 -
   1.532 -    static int getReturnOpcode(Class<?> c) {
   1.533 -        if(c == Void.TYPE) {
   1.534 -            return RETURN;
   1.535 -        }
   1.536 -        return IRETURN + getOpcodeOffset(c);
   1.537 -    }
   1.538 -
   1.539 -    private static int getOpcodeOffset(Class<?> c) {
   1.540 -        if (c.isPrimitive()) {
   1.541 -            if (c == Long.TYPE) {
   1.542 -                return 1;
   1.543 -            } else if (c == Float.TYPE) {
   1.544 -                return 2;
   1.545 -            } else if (c == Double.TYPE) {
   1.546 -                return 3;
   1.547 -            }
   1.548 -            return 0;
   1.549 -        } else {
   1.550 -            return 4;
   1.551 -        }
   1.552 -    }
   1.553 -
   1.554 -}