InnerClassLambdaMetafactory 内部类Lambda元工厂 源码解析

InnerClassLambdaMetafactory 内部类Lambda元工厂

类介绍

InnerClassLambdaMetafactory 是 Java 中用于生成 lambda 表达式实现类的一个关键类。它的主要功能是在运行时动态生成一个内部类来实现函数式接口。下面是对这个类的一些关键点的解释:

  1. 作用:

    • 动态生成实现函数式接口的内部类
    • 处理 lambda 表达式的序列化(如果需要)
    • 创建桥接方法(如果需要)
  2. 主要字段:

    • implMethodClassName:实现方法的类名
    • implMethodName:实现方法的名称
    • implMethodDesc:实现方法的描述符
    • constructorType:生成的类的构造函数类型
    • lambdaClassName:生成的 lambda 类的名称
  3. 核心方法:

    • 构造函数:初始化各种必要的字段和参数
    • spinInnerClass():生成内部类的字节码
    • generateConstructor():为生成的类创建构造函数
    • generateMethod():生成实现函数式接口方法的代码
  4. 工作流程:

    • 接收 lambda 表达式的相关信息(方法引用、捕获的变量等)
    • 使用 ASM 库动态生成实现函数式接口的内部类
    • 处理序列化和桥接方法(如果需要)
    • 返回一个 CallSite,用于后续的方法调用
  5. 优势:

    • 运行时动态生成代码,避免编译时生成大量内部类
    • 可以处理复杂的 lambda 表达式,包括捕获变量和方法引用
    • 支持 lambda 表达式的序列化

这个类是 Java 8 引入 lambda 表达式后,在 JVM 层面实现 lambda 的核心机制之一,它使得 Java 能够高效地支持函数式编程范式。

源码

/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.lang.invoke;

import jdk.internal.org.objectweb.asm.*;
import sun.invoke.util.BytecodeDescriptor;
import sun.misc.Unsafe;
import sun.security.action.GetPropertyAction;

import java.io.FilePermission;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.LinkedHashSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.PropertyPermission;
import java.util.Set;

import static jdk.internal.org.objectweb.asm.Opcodes.*;

/**
 * Lambda metafactory implementation which dynamically creates an
 * inner-class-like class per lambda callsite.
 *
 * @see LambdaMetafactory
 */
/* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
    private static final Unsafe UNSAFE = Unsafe.getUnsafe();

    private static final int CLASSFILE_VERSION = 52;
    private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
    private static final String JAVA_LANG_OBJECT = "java/lang/Object";
    private static final String NAME_CTOR = "<init>";
    private static final String NAME_FACTORY = "get$Lambda";

    //Serialization support
    private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
    private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException";
    private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
    private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V";
    private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V";
    private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
    private static final String NAME_METHOD_READ_OBJECT = "readObject";
    private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
    private static final String DESCR_CTOR_SERIALIZED_LAMBDA
            = MethodType.methodType(void.class,
                                    Class.class,
                                    String.class, String.class, String.class,
                                    int.class, String.class, String.class, String.class,
                                    String.class,
                                    Object[].class).toMethodDescriptorString();
    private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION
            = MethodType.methodType(void.class, String.class).toMethodDescriptorString();
    private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION};


    private static final String[] EMPTY_STRING_ARRAY = new String[0];

    // Used to ensure that each spun class name is unique
    private static final AtomicInteger counter = new AtomicInteger(0);

    // For dumping generated classes to disk, for debugging purposes
    private static final ProxyClassesDumper dumper;

    static {
        final String key = "jdk.internal.lambda.dumpProxyClasses";
        String path = AccessController.doPrivileged(
                new GetPropertyAction(key), null,
                new PropertyPermission(key , "read"));
        dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path);
    }

    // See context values in AbstractValidatingLambdaMetafactory
    private final String implMethodClassName;        // Name of type containing implementation "CC"
    private final String implMethodName;             // Name of implementation method "impl"
    private final String implMethodDesc;             // Type descriptor for implementation methods "(I)Ljava/lang/String;"
    private final Class<?> implMethodReturnClass;    // class for implementaion method return type "Ljava/lang/String;"
    private final MethodType constructorType;        // Generated class constructor type "(CC)void"
    private final ClassWriter cw;                    // ASM class writer
    private final String[] argNames;                 // Generated names for the constructor arguments
    private final String[] argDescs;                 // Type descriptors for the constructor arguments
    private final String lambdaClassName;            // Generated name for the generated class "X$$Lambda$1"


    /**
     * General meta-factory constructor, supporting both standard cases and
     * allowing for uncommon options such as serialization or bridging.
     *
     * @param caller Stacked automatically by VM; represents a lookup context
     *               with the accessibility privileges of the caller.
     * @param invokedType Stacked automatically by VM; the signature of the
     *                    invoked method, which includes the expected static
     *                    type of the returned lambda object, and the static
     *                    types of the captured arguments for the lambda.  In
     *                    the event that the implementation method is an
     *                    instance method, the first argument in the invocation
     *                    signature will correspond to the receiver.
     * @param samMethodName Name of the method in the functional interface to
     *                      which the lambda or method reference is being
     *                      converted, represented as a String.
     * @param samMethodType Type of the method in the functional interface to
     *                      which the lambda or method reference is being
     *                      converted, represented as a MethodType.
     * @param implMethod The implementation method which should be called (with
     *                   suitable adaptation of argument types, return types,
     *                   and adjustment for captured arguments) when methods of
     *                   the resulting functional interface instance are invoked.
     * @param instantiatedMethodType The signature of the primary functional
     *                               interface method after type variables are
     *                               substituted with their instantiation from
     *                               the capture site
     * @param isSerializable Should the lambda be made serializable?  If set,
     *                       either the target type or one of the additional SAM
     *                       types must extend {@code Serializable}.
     * @param markerInterfaces Additional interfaces which the lambda object
     *                       should implement.
     * @param additionalBridges Method types for additional signatures to be
     *                          bridged to the implementation method
     * @throws LambdaConversionException If any of the meta-factory protocol
     * invariants are violated
     */
    public InnerClassLambdaMetafactory(MethodHandles.Lookup caller,
                                       MethodType invokedType,
                                       String samMethodName,
                                       MethodType samMethodType,
                                       MethodHandle implMethod,
                                       MethodType instantiatedMethodType,
                                       boolean isSerializable,
                                       Class<?>[] markerInterfaces,
                                       MethodType[] additionalBridges)
            throws LambdaConversionException {
        super(caller, invokedType, samMethodName, samMethodType,
              implMethod, instantiatedMethodType,
              isSerializable, markerInterfaces, additionalBridges);
        implMethodClassName = implDefiningClass.getName().replace('.', '/');
        implMethodName = implInfo.getName();
        implMethodDesc = implMethodType.toMethodDescriptorString();
        implMethodReturnClass = (implKind == MethodHandleInfo.REF_newInvokeSpecial)
                ? implDefiningClass
                : implMethodType.returnType();
        constructorType = invokedType.changeReturnType(Void.TYPE);
        lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet();
        cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        int parameterCount = invokedType.parameterCount();
        if (parameterCount > 0) {
            argNames = new String[parameterCount];
            argDescs = new String[parameterCount];
            for (int i = 0; i < parameterCount; i++) {
                argNames[i] = "arg$" + (i + 1);
                argDescs[i] = BytecodeDescriptor.unparse(invokedType.parameterType(i));
            }
        } else {
            argNames = argDescs = EMPTY_STRING_ARRAY;
        }
    }

    /**
     * Build the CallSite. Generate a class file which implements the functional
     * interface, define the class, if there are no parameters create an instance
     * of the class which the CallSite will return, otherwise, generate handles
     * which will call the class' constructor.
     *
     * @return a CallSite, which, when invoked, will return an instance of the
     * functional interface
     * @throws ReflectiveOperationException
     * @throws LambdaConversionException If properly formed functional interface
     * is not found
     */
    @Override
    CallSite buildCallSite() throws LambdaConversionException {
        final Class<?> innerClass = spinInnerClass();
        if (invokedType.parameterCount() == 0) {
            final Constructor<?>[] ctrs = AccessController.doPrivileged(
                    new PrivilegedAction<Constructor<?>[]>() {
                @Override
                public Constructor<?>[] run() {
                    Constructor<?>[] ctrs = innerClass.getDeclaredConstructors();
                    if (ctrs.length == 1) {
                        // The lambda implementing inner class constructor is private, set
                        // it accessible (by us) before creating the constant sole instance
                        ctrs[0].setAccessible(true);
                    }
                    return ctrs;
                }
                    });
            if (ctrs.length != 1) {
                throw new LambdaConversionException("Expected one lambda constructor for "
                        + innerClass.getCanonicalName() + ", got " + ctrs.length);
            }

            try {
                Object inst = ctrs[0].newInstance();
                return new ConstantCallSite(MethodHandles.constant(samBase, inst));
            }
            catch (ReflectiveOperationException e) {
                throw new LambdaConversionException("Exception instantiating lambda object", e);
            }
        } else {
            try {
                UNSAFE.ensureClassInitialized(innerClass);
                return new ConstantCallSite(
                        MethodHandles.Lookup.IMPL_LOOKUP
                             .findStatic(innerClass, NAME_FACTORY, invokedType));
            }
            catch (ReflectiveOperationException e) {
                throw new LambdaConversionException("Exception finding constructor", e);
            }
        }
    }

    /**
     * Generate a class file which implements the functional
     * interface, define and return the class.
     *
     * @implNote The class that is generated does not include signature
     * information for exceptions that may be present on the SAM method.
     * This is to reduce classfile size, and is harmless as checked exceptions
     * are erased anyway, no one will ever compile against this classfile,
     * and we make no guarantees about the reflective properties of lambda
     * objects.
     *
     * @return a Class which implements the functional interface
     * @throws LambdaConversionException If properly formed functional interface
     * is not found
     */
    private Class<?> spinInnerClass() throws LambdaConversionException {
        String[] interfaces;
        String samIntf = samBase.getName().replace('.', '/');
        boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase);
        if (markerInterfaces.length == 0) {
            interfaces = new String[]{samIntf};
        } else {
            // Assure no duplicate interfaces (ClassFormatError)
            Set<String> itfs = new LinkedHashSet<>(markerInterfaces.length + 1);
            itfs.add(samIntf);
            for (Class<?> markerInterface : markerInterfaces) {
                itfs.add(markerInterface.getName().replace('.', '/'));
                accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(markerInterface);
            }
            interfaces = itfs.toArray(new String[itfs.size()]);
        }

        cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
                 lambdaClassName, null,
                 JAVA_LANG_OBJECT, interfaces);

        // Generate final fields to be filled in by constructor
        for (int i = 0; i < argDescs.length; i++) {
            FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL,
                                            argNames[i],
                                            argDescs[i],
                                            null, null);
            fv.visitEnd();
        }

        generateConstructor();

        if (invokedType.parameterCount() != 0) {
            generateFactory();
        }

        // Forward the SAM method
        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
                                          samMethodType.toMethodDescriptorString(), null, null);
        mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
        new ForwardingMethodGenerator(mv).generate(samMethodType);

        // Forward the bridges
        if (additionalBridges != null) {
            for (MethodType mt : additionalBridges) {
                mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName,
                                    mt.toMethodDescriptorString(), null, null);
                mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
                new ForwardingMethodGenerator(mv).generate(mt);
            }
        }

        if (isSerializable)
            generateSerializationFriendlyMethods();
        else if (accidentallySerializable)
            generateSerializationHostileMethods();

        cw.visitEnd();

        // Define the generated class in this VM.

        final byte[] classBytes = cw.toByteArray();

        // If requested, dump out to a file for debugging purposes
        if (dumper != null) {
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                @Override
                public Void run() {
                    dumper.dumpClass(lambdaClassName, classBytes);
                    return null;
                }
            }, null,
            new FilePermission("<<ALL FILES>>", "read, write"),
            // createDirectories may need it
            new PropertyPermission("user.dir", "read"));
        }

        return UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
    }

    /**
     * Generate the factory method for the class
     */
    private void generateFactory() {
        MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null);
        m.visitCode();
        m.visitTypeInsn(NEW, lambdaClassName);
        m.visitInsn(Opcodes.DUP);
        int parameterCount = invokedType.parameterCount();
        for (int typeIndex = 0, varIndex = 0; typeIndex < parameterCount; typeIndex++) {
            Class<?> argType = invokedType.parameterType(typeIndex);
            m.visitVarInsn(getLoadOpcode(argType), varIndex);
            varIndex += getParameterSize(argType);
        }
        m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString(), false);
        m.visitInsn(ARETURN);
        m.visitMaxs(-1, -1);
        m.visitEnd();
    }

    /**
     * Generate the constructor for the class
     */
    private void generateConstructor() {
        // Generate constructor
        MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR,
                                            constructorType.toMethodDescriptorString(), null, null);
        ctor.visitCode();
        ctor.visitVarInsn(ALOAD, 0);
        ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR,
                             METHOD_DESCRIPTOR_VOID, false);
        int parameterCount = invokedType.parameterCount();
        for (int i = 0, lvIndex = 0; i < parameterCount; i++) {
            ctor.visitVarInsn(ALOAD, 0);
            Class<?> argType = invokedType.parameterType(i);
            ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
            lvIndex += getParameterSize(argType);
            ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]);
        }
        ctor.visitInsn(RETURN);
        // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
        ctor.visitMaxs(-1, -1);
        ctor.visitEnd();
    }

    /**
     * Generate a writeReplace method that supports serialization
     */
    private void generateSerializationFriendlyMethods() {
        TypeConvertingMethodAdapter mv
                = new TypeConvertingMethodAdapter(
                    cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
                    NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE,
                    null, null));

        mv.visitCode();
        mv.visitTypeInsn(NEW, NAME_SERIALIZED_LAMBDA);
        mv.visitInsn(DUP);
        mv.visitLdcInsn(Type.getType(targetClass));
        mv.visitLdcInsn(invokedType.returnType().getName().replace('.', '/'));
        mv.visitLdcInsn(samMethodName);
        mv.visitLdcInsn(samMethodType.toMethodDescriptorString());
        mv.visitLdcInsn(implInfo.getReferenceKind());
        mv.visitLdcInsn(implInfo.getDeclaringClass().getName().replace('.', '/'));
        mv.visitLdcInsn(implInfo.getName());
        mv.visitLdcInsn(implInfo.getMethodType().toMethodDescriptorString());
        mv.visitLdcInsn(instantiatedMethodType.toMethodDescriptorString());
        mv.iconst(argDescs.length);
        mv.visitTypeInsn(ANEWARRAY, JAVA_LANG_OBJECT);
        for (int i = 0; i < argDescs.length; i++) {
            mv.visitInsn(DUP);
            mv.iconst(i);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
            mv.boxIfTypePrimitive(Type.getType(argDescs[i]));
            mv.visitInsn(AASTORE);
        }
        mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR,
                DESCR_CTOR_SERIALIZED_LAMBDA, false);
        mv.visitInsn(ARETURN);
        // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
        mv.visitMaxs(-1, -1);
        mv.visitEnd();
    }

    /**
     * Generate a readObject/writeObject method that is hostile to serialization
     */
    private void generateSerializationHostileMethods() {
        MethodVisitor mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
                                          NAME_METHOD_WRITE_OBJECT, DESCR_METHOD_WRITE_OBJECT,
                                          null, SER_HOSTILE_EXCEPTIONS);
        mv.visitCode();
        mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION);
        mv.visitInsn(DUP);
        mv.visitLdcInsn("Non-serializable lambda");
        mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
                           DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION, false);
        mv.visitInsn(ATHROW);
        mv.visitMaxs(-1, -1);
        mv.visitEnd();

        mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
                            NAME_METHOD_READ_OBJECT, DESCR_METHOD_READ_OBJECT,
                            null, SER_HOSTILE_EXCEPTIONS);
        mv.visitCode();
        mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION);
        mv.visitInsn(DUP);
        mv.visitLdcInsn("Non-serializable lambda");
        mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
                           DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION, false);
        mv.visitInsn(ATHROW);
        mv.visitMaxs(-1, -1);
        mv.visitEnd();
    }

    /**
     * This class generates a method body which calls the lambda implementation
     * method, converting arguments, as needed.
     */
    private class ForwardingMethodGenerator extends TypeConvertingMethodAdapter {

        ForwardingMethodGenerator(MethodVisitor mv) {
            super(mv);
        }

        void generate(MethodType methodType) {
            visitCode();

            if (implKind == MethodHandleInfo.REF_newInvokeSpecial) {
                visitTypeInsn(NEW, implMethodClassName);
                visitInsn(DUP);
            }
            for (int i = 0; i < argNames.length; i++) {
                visitVarInsn(ALOAD, 0);
                visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
            }

            convertArgumentTypes(methodType);

            // Invoke the method we want to forward to
            visitMethodInsn(invocationOpcode(), implMethodClassName,
                            implMethodName, implMethodDesc,
                            implDefiningClass.isInterface());

            // Convert the return value (if any) and return it
            // Note: if adapting from non-void to void, the 'return'
            // instruction will pop the unneeded result
            Class<?> samReturnClass = methodType.returnType();
            convertType(implMethodReturnClass, samReturnClass, samReturnClass);
            visitInsn(getReturnOpcode(samReturnClass));
            // Maxs computed by ClassWriter.COMPUTE_MAXS,these arguments ignored
            visitMaxs(-1, -1);
            visitEnd();
        }

        private void convertArgumentTypes(MethodType samType) {
            int lvIndex = 0;
            boolean samIncludesReceiver = implIsInstanceMethod &&
                                                   invokedType.parameterCount() == 0;
            int samReceiverLength = samIncludesReceiver ? 1 : 0;
            if (samIncludesReceiver) {
                // push receiver
                Class<?> rcvrType = samType.parameterType(0);
                visitVarInsn(getLoadOpcode(rcvrType), lvIndex + 1);
                lvIndex += getParameterSize(rcvrType);
                convertType(rcvrType, implDefiningClass, instantiatedMethodType.parameterType(0));
            }
            int samParametersLength = samType.parameterCount();
            int argOffset = implMethodType.parameterCount() - samParametersLength;
            for (int i = samReceiverLength; i < samParametersLength; i++) {
                Class<?> argType = samType.parameterType(i);
                visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
                lvIndex += getParameterSize(argType);
                convertType(argType, implMethodType.parameterType(argOffset + i), instantiatedMethodType.parameterType(i));
            }
        }

        private int invocationOpcode() throws InternalError {
            switch (implKind) {
                case MethodHandleInfo.REF_invokeStatic:
                    return INVOKESTATIC;
                case MethodHandleInfo.REF_newInvokeSpecial:
                    return INVOKESPECIAL;
                 case MethodHandleInfo.REF_invokeVirtual:
                    return INVOKEVIRTUAL;
                case MethodHandleInfo.REF_invokeInterface:
                    return INVOKEINTERFACE;
                case MethodHandleInfo.REF_invokeSpecial:
                    return INVOKESPECIAL;
                default:
                    throw new InternalError("Unexpected invocation kind: " + implKind);
            }
        }
    }

    static int getParameterSize(Class<?> c) {
        if (c == Void.TYPE) {
            return 0;
        } else if (c == Long.TYPE || c == Double.TYPE) {
            return 2;
        }
        return 1;
    }

    static int getLoadOpcode(Class<?> c) {
        if(c == Void.TYPE) {
            throw new InternalError("Unexpected void type of load opcode");
        }
        return ILOAD + getOpcodeOffset(c);
    }

    static int getReturnOpcode(Class<?> c) {
        if(c == Void.TYPE) {
            return RETURN;
        }
        return IRETURN + getOpcodeOffset(c);
    }

    private static int getOpcodeOffset(Class<?> c) {
        if (c.isPrimitive()) {
            if (c == Long.TYPE) {
                return 1;
            } else if (c == Float.TYPE) {
                return 2;
            } else if (c == Double.TYPE) {
                return 3;
            }
            return 0;
        } else {
            return 4;
        }
    }

}

源码解释


package java.lang.invoke;

import jdk.internal.org.objectweb.asm.*;
import sun.invoke.util.BytecodeDescriptor;
import sun.misc.Unsafe;
import sun.security.action.GetPropertyAction;

import java.io.FilePermission;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.LinkedHashSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.PropertyPermission;
import java.util.Set;

import static jdk.internal.org.objectweb.asm.Opcodes.*;

/**
 * Lambda元工厂实现,它为每个Lambda调用站点动态创建一个内部类。
 *
 * @see LambdaMetafactory
 * /* package */ 表示这个类是包级私有的,只能在同一个包内部被访问。
 * final 关键字表示这个类不能被继承。
 */
/* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
    // 获取Unsafe实例,用于低级操作,如直接内存访问
	private static final Unsafe UNSAFE = Unsafe.getUnsafe();
	
	// 类文件版本号,Java 8对应52
	private static final int CLASSFILE_VERSION = 52;
	// 表示void类型的方法描述符
	private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
	// Java中Object类的内部名称
	private static final String JAVA_LANG_OBJECT = "java/lang/Object";
	// 构造函数的特殊名称
	private static final String NAME_CTOR = "<init>";
	// 工厂方法的名称
	private static final String NAME_FACTORY = "get$Lambda";
	
	// 序列化支持相关常量
	private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
	private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException";
	private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
	private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V";
	private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V";
	private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
	private static final String NAME_METHOD_READ_OBJECT = "readObject";
	private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
	// SerializedLambda构造函数的描述符
	private static final String DESCR_CTOR_SERIALIZED_LAMBDA
	        = MethodType.methodType(void.class,
	                                Class.class,
	                                String.class, String.class, String.class,
	                                int.class, String.class, String.class, String.class,
	                                String.class,
	                                Object[].class).toMethodDescriptorString();
	// NotSerializableException构造函数的描述符
	private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION
	        = MethodType.methodType(void.class, String.class).toMethodDescriptorString();
	// 不支持序列化的异常列表
	private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION};
	
	// 空字符串数组常量
	private static final String[] EMPTY_STRING_ARRAY = new String[0];
	
	// 用于确保每个生成的类名是唯一的计数器
	private static final AtomicInteger counter = new AtomicInteger(0);
	
	// 用于调试目的,将生成的类转储到磁盘
	private static final ProxyClassesDumper dumper;
	
	// 静态初始化块,用于初始化dumper
	static {
	    /**
		 * 获取并设置代理类转储功能
		 */
		// 定义系统属性的键名,用于控制是否转储内部lambda代理类
		final String key = "jdk.internal.lambda.dumpProxyClasses";
		
		// 使用AccessController执行特权操作,获取系统属性值
		String path = AccessController.doPrivileged(
		        new GetPropertyAction(key), // 创建获取属性的动作
		        null, // 不指定AccessControlContext
		        new PropertyPermission(key , "read") // 指定所需的权限
		);

		// 根据获取的路径创建ProxyClassesDumper实例
		// 如果路径为null,则不启用转储功能
		dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path);

	}
	
	// 实现方法所在类的名称
	private final String implMethodClassName;
	// 实现方法的名称
	private final String implMethodName;
	// 实现方法的描述符
	private final String implMethodDesc;
	// 实现方法返回类型的类
	private final Class<?> implMethodReturnClass;
	// 生成的类构造函数的类型
	private final MethodType constructorType;
	// ASM类写入器
	private final ClassWriter cw;
	// 构造函数参数的生成名称
	private final String[] argNames;
	// 构造函数参数的类型描述符
	private final String[] argDescs;
	// 生成的类的名称
	private final String lambdaClassName;

    /**
	 * 构造函数:创建一个内部类Lambda元工厂的实例。
	 * 该构造函数用于支持标准情况以及允许序列化或桥接等不常见选项。
	 *
	 * @param caller 由VM自动堆叠;代表具有调用者访问权限的查找上下文。
	 * @param invokedType 由VM自动堆叠;被调用方法的签名,包括返回的lambda对象的预期静态类型,
	 *                    以及lambda捕获参数的静态类型。如果实现方法是实例方法,调用签名的第一个参数将对应于接收者。
	 * @param samMethodName 转换为lambda或方法引用的函数接口中的方法名称,表示为String。
	 * @param samMethodType 转换为lambda或方法引用的函数接口中的方法类型,表示为MethodType。
	 * @param implMethod 应当被调用的实现方法(适当调整参数类型、返回类型和捕获参数后),当调用结果函数接口实例的方法时。
	 * @param instantiatedMethodType 在从捕获站点实例化类型变量后,主要函数接口方法的签名。
	 * @param isSerializable lambda是否应该是可序列化的?如果设置,目标类型或一个附加的SAM类型必须扩展{@code Serializable}。
	 * @param markerInterfaces lambda对象应该实现的附加接口。
	 * @param additionalBridges 额外的签名,这些签名将被桥接到实现方法。
	 * @throws LambdaConversionException 如果违反了元工厂协议的任何不变量。
	 */
    public InnerClassLambdaMetafactory(MethodHandles.Lookup caller,
                                       MethodType invokedType,
                                       String samMethodName,
                                       MethodType samMethodType,
                                       MethodHandle implMethod,
                                       MethodType instantiatedMethodType,
                                       boolean isSerializable,
                                       Class<?>[] markerInterfaces,
                                       MethodType[] additionalBridges)
            throws LambdaConversionException {
        // 调用父类构造函数,初始化基本参数
	    super(caller, invokedType, samMethodName, samMethodType,
	          implMethod, instantiatedMethodType,
	          isSerializable, markerInterfaces, additionalBridges);
	    // 初始化实现方法的类名,将'.'替换为'/'
	    implMethodClassName = implDefiningClass.getName().replace('.', '/');
	    // 初始化实现方法的名称
	    implMethodName = implInfo.getName();
	    // 初始化实现方法的描述符
	    implMethodDesc = implMethodType.toMethodDescriptorString();
	    // 初始化实现方法返回类型的类
	    implMethodReturnClass = (implKind == MethodHandleInfo.REF_newInvokeSpecial)
	            ? implDefiningClass
	            : implMethodType.returnType();
	    // 初始化生成类构造函数的类型
	    constructorType = invokedType.changeReturnType(Void.TYPE);
	    // 生成并初始化lambda类的名称
	    lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet();
	    // 【重要⭐️⭐️⭐️⭐️⭐️】初始化ASM类写入器
	    cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
	    // 初始化构造函数参数名称和描述符数组
	    int parameterCount = invokedType.parameterCount();
	    if (parameterCount > 0) {
	       // 初始化参数名和参数描述数组,大小为方法参数的数量
			argNames = new String[parameterCount];
			argDescs = new String[parameterCount];
			// 遍历所有参数,生成参数名和参数描述
			for (int i = 0; i < parameterCount; i++) {
			    // 为每个参数生成一个唯一的名称,格式为"arg$序号"
			    argNames[i] = "arg$" + (i + 1);
			    // 使用BytecodeDescriptor工具类将参数类型转换为字符串描述形式
			    argDescs[i] = BytecodeDescriptor.unparse(invokedType.parameterType(i));
			}

	    } else {
	        // 当调用类型参数计数为0时,初始化参数名和参数描述数组为空字符串数组
			argNames = argDescs = EMPTY_STRING_ARRAY;
	    }
    }

   /**
	 * 构建CallSite。生成实现功能接口的类文件,定义类,如果没有参数则创建类的实例,
	 * 该实例将由CallSite返回,否则,生成的句柄将调用类的构造函数。
	 *
	 * @return CallSite,调用时,将返回一个功能接口的实例
	 * @throws ReflectiveOperationException 反射操作异常
	 * @throws LambdaConversionException 如果没有找到正确形式的功能接口
	 */
    @Override
    CallSite buildCallSite() throws LambdaConversionException {
         // 生成实现了函数接口的内部类
	    final Class<?> innerClass = spinInnerClass();
	    // 如果调用类型没有参数,即无需捕获的变量
	    if (invokedType.parameterCount() == 0) {
	        // 通过反射获取一个内部类的所有构造函数,并在只有一个构造函数的情况下,将这个唯一的构造函数设置为可访问的。
	        final Constructor<?>[] ctrs = AccessController.doPrivileged(
	                new PrivilegedAction<Constructor<?>[]>() {
	            @Override
	            public Constructor<?>[] run() {
	            	// 返回了innerClass(内部类)的所有构造函数,包括私有的。
	                Constructor<?>[] ctrs = innerClass.getDeclaredConstructors();
	                if (ctrs.length == 1) {
	                    // 如果只有一个构造函数,设置为可访问
	                    ctrs[0].setAccessible(true);
	                }
	                return ctrs;
	            }
	                });
	        // 确保只有一个构造函数
	        if (ctrs.length != 1) {
	            throw new LambdaConversionException("Expected one lambda constructor for "
	                    + innerClass.getCanonicalName() + ", got " + ctrs.length);
	        }
	
	        try {
	            // 通过构造函数实例化对象
	            Object inst = ctrs[0].newInstance();
	            // 创建并返回一个持有lambda对象的ConstantCallSite
	            return new ConstantCallSite(MethodHandles.constant(samBase, inst));
	        }
	        catch (ReflectiveOperationException e) {
	            throw new LambdaConversionException("Exception instantiating lambda object", e);
	        }
	    } else {
	        // 如果有参数,需要通过静态方法来创建CallSite
	        try {
	            // 确保类已经被完全初始化
	            UNSAFE.ensureClassInitialized(innerClass);
	            // 查找静态方法并创建CallSite
	            return new ConstantCallSite(
	                    MethodHandles.Lookup.IMPL_LOOKUP
	                         .findStatic(innerClass, NAME_FACTORY, invokedType));
	        }
	        catch (ReflectiveOperationException e) {
	            throw new LambdaConversionException("Exception finding constructor", e);
	        }
	    }
    }
	/**
	 * 生成并返回一个实现了功能接口的类文件。
	 *
	 * @implNote 生成的类文件不包含SAM方法可能存在的异常签名信息,
	 * 旨在减少类文件大小。这是无害的,因为已检查的异常会被擦除,
	 * 没有人会针对这个类文件进行编译,我们不保证lambda对象的反射属性。
	 *
	 * @return 实现了功能接口的类
	 * @throws LambdaConversionException 如果没有找到正确形式的功能接口
	 */
	private Class<?> spinInnerClass() throws LambdaConversionException {
		// 构建一个字符串数组 interfaces,该数组包含了要实现的接口的内部名称(即将.替换为/的全限定类名),同时确保没有重复的接口,并检查是否意外地实现了 Serializable 接口。
	    String[] interfaces;
	    // 获取函数式接口的内部名称,将.替换为/。
	    String samIntf = samBase.getName().replace('.', '/');
	    // 检查基础函数式接口是否意外实现了 Serializable 接口。
	    boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase);
	    // 如果没有额外的标记接口,直接使用函数式接口的内部名称作为 interfaces 的唯一元素。
	    if (markerInterfaces.length == 0) {
	        interfaces = new String[]{samIntf};
	    } else {
	        // 如果 markerInterfaces 非空,确保没有重复的接口(ClassFormatError),使用 LinkedHashSet 来存储接口名称,确保不会有重复。
	        Set<String> itfs = new LinkedHashSet<>(markerInterfaces.length + 1);
	        // 将函数式接口的内部名称添加到集合中
	        itfs.add(samIntf);
	        // 遍历额外的标记接口,将它们的内部名称添加到集合中,并检查是否意外实现了 Serializable 接口。
	        for (Class<?> markerInterface : markerInterfaces) {
	            itfs.add(markerInterface.getName().replace('.', '/'));
	            accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(markerInterface);
	        }
	        // 将接口名称集合转换为字符串数组。
	        interfaces = itfs.toArray(new String[itfs.size()]);
	    }
		/**
		cw 是 ClassWriter 的实例,它是 ASM(一个通用的 Java 字节码操作和分析框架)库中的一个类。ClassWriter 用于动态生成类或接口的二进制字节码。在上下文中,cw 被用来构建和定义一个新的类,这个类是在运行时动态生成的,用于实现特定的功能接口,通常是为了支持 Java 中的 lambda 表达式。
通过调用 ClassWriter 的方法,如 visit、visitMethod 和 visitField,可以分别定义类的基本信息、方法和字段。最终,通过调用 cw.toByteArray() 方法,可以获取到这个动态生成的类的字节码数组,这个数组可以被加载到 JVM 中,从而创建出一个新的类实例。
		*/
		// 定义了一个类,这个类是final和synthetic的,继承自Object类,并实现了interfaces数组中指定的接口。lambdaClassName是这个类的名称。
		// 其中:
		// 	ACC_FINAL 表示这个类是final的
		//	ACC_SYNTHETIC 表示这个类是synthetic的,synthetic标记表明这个类是由编译器自动生成的,而非直接来自源代码。
		//	lambdaClassName 是动态生成的类名
	    cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
	             lambdaClassName, null,
	             JAVA_LANG_OBJECT, interfaces);
	
	    // 生成构造函数中要填充的最终字段
	    for (int i = 0; i < argDescs.length; i++) {
	    	// 生成一个private final字段来存储这些参数的值。
	        FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL,
	                                        argNames[i],
	                                        argDescs[i],
	                                        null, null);
	        /**
				这行代码的作用是结束一个字段的访问。在ASM中,每当开始定义一个新的字段时,都会通过调用visitField方法返回一个FieldVisitor对象,通过这个对象可以定义字段的属性。当字段的定义结束时,需要调用visitEnd方法来标志这个过程的结束。
			*/                                
	        fv.visitEnd();
	    }
		// 生成构造函数
	    generateConstructor();
		// 判断是检查invokedType(lambda表达式的目标类型)是否有参数。
	    if (invokedType.parameterCount() != 0) {
	    	// 这个方法的作用是生成工厂方法。工厂方法是一个特殊的方法,用于动态生成并返回实现了函数式接口的类的实例。这个过程通常涉及到字节码的生成和类的加载。
	        generateFactory();
	    }
	
	    /**
		    这行代码通过调用 ClassWriter 的 visitMethod 方法创建了一个新的方法。这个方法的访问级别是 public,方法名是 samMethodName,这是一个从外部传入的参数,表示要实现的SAM接口中的方法名。samMethodType.toMethodDescriptorString() 将方法的签名转换为字符串形式,用于定义方法的参数类型和返回类型。最后两个 null 参数分别表示这个方法的签名和异常,这里不使用这些高级特性,所以传入 null。
		*/
	    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
	                                      samMethodType.toMethodDescriptorString(), null, null);
	    // 这行代码给刚才创建的方法添加了一个注解 LambdaForm$Hidden。这个注解是内部使用的,用于标记这个方法不应该被外部调用或者看到。true 参数表示这个注解是在运行时可见的。
	    mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
	    // 这行代码实际上是生成方法体的关键步骤。它创建了一个 ForwardingMethodGenerator 对象,这个对象负责生成方法体的字节码。generate 方法接受一个 MethodType 对象 samMethodType 作为参数,这个对象描述了SAM接口方法的参数类型和返回类型。generate 方法根据这个信息,动态生成字节码,这些字节码实现了将调用转发到实际的目标方法上。
	    new ForwardingMethodGenerator(mv).generate(samMethodType);
	
	
	    /**
			这段代码的主要作用是为了生成桥接方法(Bridge Methods),这些方法用于处理泛型擦除后的类型不匹配问题。在Java中,泛型信息在编译时会被擦除,而桥接方法则用于在运行时保持类型的正确性。这段代码是在动态生成的类中添加这些桥接方法的过程。
	    */
	    // additionalBridges 是一个包含了需要生成桥接方法的 MethodType 对象的数组。
	    if (additionalBridges != null) {
	        for (MethodType mt : additionalBridges) {
	        	// 为每个桥接方法类型生成方法:通过调用 cw.visitMethod 方法生成桥接方法。这里的 cw 是一个 ClassWriter 对象,用于动态生成类的字节码。ACC_PUBLIC|ACC_BRIDGE 是方法的访问标志,表示这是一个公开的桥接方法。samMethodName 是要实现的函数式接口的方法名,mt.toMethodDescriptorString() 将方法类型转换为方法描述符字符串,用于指定方法的签名。
	            mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName,
	                                mt.toMethodDescriptorString(), null, null);
				// 添加方法注解:通过调用 mv.visitAnnotation 方法为生成的桥接方法添加注解。这里的注解是 "Ljava/lang/invoke/LambdaForm$Hidden;",表示这个方法是由lambda表达式生成的,不应该被直接调用。
	            mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
	            // 生成方法体:通过创建一个新的 ForwardingMethodGenerator 对象并调用其 generate 方法来生成桥接方法的方法体。这个方法体基本上是将调用转发到实际的实现方法上。
	            new ForwardingMethodGenerator(mv).generate(mt);
	        }
	    }
	
		/**
			这段代码的作用是根据是否需要序列化,生成对应的方法。具体来说,如果需要生成的类是可序列化的,则生成序列化友好的方法;如果不是故意的可序列化(即无意中成为可序列化的),则生成序列化敌对的方法。最后,调用 cw.visitEnd() 来完成类的定义。

				1.判断是否需要序列化:通过 if (isSerializable) 判断,如果 isSerializable 为 true,则表示需要生成的类是可序列化的,此时会调用 generateSerializationFriendlyMethods() 方法生成序列化友好的方法。
				2.判断是否无意中成为可序列化:如果 isSerializable 为 false,则进入 else if (accidentallySerializable) 判断,accidentallySerializable 为 true 表示类无意中成为了可序列化的(例如,通过实现了某个可序列化的接口)。此时会调用 generateSerializationHostileMethods() 方法生成序列化敌对的方法,这可能是为了避免序列化带来的潜在问题或性能影响。
				3.完成类的定义:无论是否需要序列化,最后都会执行 cw.visitEnd(),这是ASM库中的方法,用于完成类的定义。这一步是生成类文件的最后一步,标志着类定义的结束。
		*/
	    if (isSerializable)
	        generateSerializationFriendlyMethods();
	    else if (accidentallySerializable)
	        generateSerializationHostileMethods();
	
	    cw.visitEnd();
	
		// 这行代码调用 ClassWriter 对象的 toByteArray 方法,将动态生成的类转换为字节码数组。cw 是 ClassWriter 的实例,它负责生成类的字节码。
	    final byte[] classBytes = cw.toByteArray();
	
		/**
			这段代码首先检查 dumper 对象是否为 null。dumper 是一个可能用于将字节码写入文件的工具对象。如果 dumper 不为 null,则执行以下步骤:
				1.使用 AccessController.doPrivileged 方法执行一个特权操作。这是因为写入文件可能需要特定的权限,特别是在启用了安全管理器的环境中。
				2.在 doPrivileged 方法中,执行一个 PrivilegedAction,其 run 方法调用 dumper.dumpClass 方法,将类名 lambdaClassName 和字节码数组 classBytes 传递给它,以便将字节码写入文件。
				3.doPrivileged 方法的第二个参数是 null,表示不使用特定的 AccessControlContext。
				4.第三和第四个参数是 FilePermission 和 PropertyPermission 对象,分别授予读写所有文件的权限和读取用户当前目录的权限。这些权限是执行文件写入操作所必需的。
		*/
	    // 转储到文件
	    if (dumper != null) {
	        AccessController.doPrivileged(new PrivilegedAction<Void>() {
	            @Override
	            public Void run() {
	                dumper.dumpClass(lambdaClassName, classBytes);
	                return null;
	            }
	        }, null,
	        new FilePermission("<<ALL FILES>>", "read, write"),
	        // 创建目录可能需要它
	        new PropertyPermission("user.dir", "read"));
	    }
	    /**
	    	1.代码的作用
				下面这段代码的作用是在运行时动态定义一个匿名类。UNSAFE.defineAnonymousClass 方法接收三个参数:目标类(targetClass),类的字节码(classBytes),以及与类相关联的常量池补丁(这里传入的是 null)。
			2.代码的结构和逻辑
				2.1 targetClass:这是一个 Class 对象,表示新定义的匿名类将与之关联的上下文。通常,这个类是匿名类逻辑上的“宿主”类。
				2.2 classBytes:这是一个字节数组,包含了新匿名类的字节码。这些字节码通常是通过某种字节码生成库(如ASM)动态生成的。
				2.3 null:这个参数是用于类定义时的常量池补丁,这里传入 null 表示不需要进行常量池的补丁。
			3.关键代码块或语句的解释
				3.1 UNSAFE:这是 sun.misc.Unsafe 类的一个实例。Unsafe 类提供了一组底层、危险的操作,通常不推荐在标准Java代码中使用。但在某些特殊场景下,如动态类生成、低级并发控制等,Unsafe 提供的功能是必需的。
				3.2 .defineAnonymousClass(targetClass, classBytes, null):这个方法调用是动态定义匿名类的关键。它将 classBytes 中的字节码转换为一个Java类,并将这个新类与 targetClass 关联起来。由于这个类是匿名的,它没有正式的类名。传入的 null 参数表示在定义类的过程中不需要对常量池进行任何补丁操作。
	    */
	
		// 通过 Unsafe 类的 defineAnonymousClass 方法动态定义了一个匿名类,这个类的字节码由 classBytes 提供,而这个匿名类在逻辑上与 targetClass 关联。
	    return UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
	}

	/**
	 * 生成类的工厂方法
	 */
	private void generateFactory() {
	    // 开始定义工厂方法,包括访问修饰符、方法名和方法描述符
	    MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null);
	    m.visitCode(); // 开始方法的代码部分
	    m.visitTypeInsn(NEW, lambdaClassName); // 创建新的类实例
	    m.visitInsn(Opcodes.DUP); // 复制栈顶值,为了后续的构造函数调用
	    int parameterCount = invokedType.parameterCount(); // 获取参数数量
	    for (int typeIndex = 0, varIndex = 0; typeIndex < parameterCount; typeIndex++) {
	        Class<?> argType = invokedType.parameterType(typeIndex); // 获取每个参数的类型
	        m.visitVarInsn(getLoadOpcode(argType), varIndex); // 加载参数到栈上
	        varIndex += getParameterSize(argType); // 更新局部变量表索引
	    }
	    // 调用构造函数初始化对象
	    m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString(), false);
	    m.visitInsn(ARETURN); // 返回对象引用
	    m.visitMaxs(-1, -1); // 自动生成局部变量表和操作数栈大小
	    m.visitEnd(); // 结束方法的访问
	}


	/**
	 * 生成类的构造函数
	 */
	private void generateConstructor() {
	    // 创建构造方法,访问级别为private
	    MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR,
	                                        constructorType.toMethodDescriptorString(), null, null);
	    ctor.visitCode();
	    // 调用父类(Object类)的构造方法
	    ctor.visitVarInsn(ALOAD, 0);
	    ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR,
	                         METHOD_DESCRIPTOR_VOID, false);
	    // 遍历所有参数,将它们存储到字段中
	    int parameterCount = invokedType.parameterCount();
	    for (int i = 0, lvIndex = 0; i < parameterCount; i++) {
	        ctor.visitVarInsn(ALOAD, 0); // 加载this
	        Class<?> argType = invokedType.parameterType(i); // 获取参数类型
	        ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1); // 加载参数到操作数栈
	        lvIndex += getParameterSize(argType); // 计算下一个参数的本地变量表索引
	        // 将参数值存储到字段中
	        ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]);
	    }
	    ctor.visitInsn(RETURN); // 返回
	    // 使用ClassWriter.COMPUTE_MAXS计算操作数栈和本地变量表的大小,这里的参数被忽略
	    ctor.visitMaxs(-1, -1);
	    ctor.visitEnd();
	}
	
	/**
		敌对序列化(Serialization Hostile)和友好序列化(Serialization Friendly)是指对象序列化处理方式的不同策略:
			> 敌对序列化:
				>> 敌对序列化是指对象或类通过某种方式阻止自己被序列化的过程。
				>> 在Java中,这通常通过在类中实现writeObject和readObject方法,并在这些方法中抛出NotSerializableException来实现。这样,当尝试序列化或反序列化这样的对象时,会导致异常,阻止序列化过程。
				>> 敌对序列化的用途包括增强安全性,防止敏感信息被不当序列化,或者是因为对象的状态不能或不应该被保存和恢复。
			> 友好序列化:
				>> 友好序列化是指对象或类支持并优化了自己的序列化过程。
				>> 在Java中,这可以通过实现java.io.Serializable接口来实现。类可以进一步通过自定义writeObject和readObject方法来控制序列化和反序列化的具体行为,或者通过writeReplace和readResolve方法来控制序列化和反序列化时的替换逻辑。
				>> 友好序列化的目的是确保对象的状态可以被安全、有效地保存和恢复,特别是在需要将对象状态持久化或在网络间传输时。
	*/


	/**
	 * 生成一个可序列化方法(writeReplace)
	 */
	private void generateSerializationFriendlyMethods() {
	    // 创建方法访问器
	    TypeConvertingMethodAdapter mv
	            = new TypeConvertingMethodAdapter(
	                cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
	                NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE,
	                null, null));
	
	    mv.visitCode();
	    // 创建SerializedLambda实例
	    mv.visitTypeInsn(NEW, NAME_SERIALIZED_LAMBDA);
	    mv.visitInsn(DUP);
	    // 以下为调用SerializedLambda构造函数所需的参数
	    mv.visitLdcInsn(Type.getType(targetClass)); // 目标类
	    mv.visitLdcInsn(invokedType.returnType().getName().replace('.', '/')); // 返回类型
	    mv.visitLdcInsn(samMethodName); // SAM方法名
	    mv.visitLdcInsn(samMethodType.toMethodDescriptorString()); // SAM方法描述符
	    mv.visitLdcInsn(implInfo.getReferenceKind()); // 实现方法的引用类型
	    mv.visitLdcInsn(implInfo.getDeclaringClass().getName().replace('.', '/')); // 实现方法所在类
	    mv.visitLdcInsn(implInfo.getName()); // 实现方法名
	    mv.visitLdcInsn(implInfo.getMethodType().toMethodDescriptorString()); // 实现方法描述符
	    mv.visitLdcInsn(instantiatedMethodType.toMethodDescriptorString()); // 实例化方法类型描述符
	    // 创建参数数组
	    mv.iconst(argDescs.length);
	    mv.visitTypeInsn(ANEWARRAY, JAVA_LANG_OBJECT);
	    for (int i = 0; i < argDescs.length; i++) {
	        mv.visitInsn(DUP);
	        mv.iconst(i);
	        mv.visitVarInsn(ALOAD, 0); // 加载this
	        mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]); // 获取字段值
	        mv.boxIfTypePrimitive(Type.getType(argDescs[i])); // 如果是基本类型,则装箱
	        mv.visitInsn(AASTORE); // 存储到数组
	    }
	    // 调用SerializedLambda的构造函数
	    mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR,
	            DESCR_CTOR_SERIALIZED_LAMBDA, false);
	    mv.visitInsn(ARETURN); // 返回SerializedLambda对象
	    // 设置最大栈大小和局部变量表大小,这里由ClassWriter计算
	    mv.visitMaxs(-1, -1);
	    mv.visitEnd();
	}

	/**
	 * 生成对序列化敌对的readObject/writeObject方法
	 */
	private void generateSerializationHostileMethods() {
	    // 创建writeObject方法,抛出NotSerializableException异常,阻止序列化
	    MethodVisitor mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
	                                      NAME_METHOD_WRITE_OBJECT, DESCR_METHOD_WRITE_OBJECT,
	                                      null, SER_HOSTILE_EXCEPTIONS);
	    mv.visitCode();
	    mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION); // 实例化NotSerializableException
	    mv.visitInsn(DUP);
	    mv.visitLdcInsn("Non-serializable lambda"); // 设置异常信息
	    mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
	                       DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION, false); // 调用NotSerializableException的构造函数
	    mv.visitInsn(ATHROW); // 抛出异常
	    mv.visitMaxs(-1, -1);
	    mv.visitEnd();
	
	    // 创建readObject方法,抛出NotSerializableException异常,阻止反序列化
	    mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
	                        NAME_METHOD_READ_OBJECT, DESCR_METHOD_READ_OBJECT,
	                        null, SER_HOSTILE_EXCEPTIONS);
	    mv.visitCode();
	    mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION); // 实例化NotSerializableException
	    mv.visitInsn(DUP);
	    mv.visitLdcInsn("Non-serializable lambda"); // 设置异常信息
	    mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
	                       DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION, false); // 调用NotSerializableException的构造函数
	    mv.visitInsn(ATHROW); // 抛出异常
	    mv.visitMaxs(-1, -1);
	    mv.visitEnd();
	}

	/**
	 * 这个类生成的方法体会调用lambda实现方法,必要时转换参数。
	 */
	private class ForwardingMethodGenerator extends TypeConvertingMethodAdapter {
	
	    ForwardingMethodGenerator(MethodVisitor mv) {
	        super(mv);
	    }
	
	    void generate(MethodType methodType) {
	        visitCode();
	        // 如果实现方法是构造函数,需要先创建对象
	        if (implKind == MethodHandleInfo.REF_newInvokeSpecial) {
	            visitTypeInsn(NEW, implMethodClassName);
	            visitInsn(DUP);
	        }
	        // 加载lambda捕获的参数
	        for (int i = 0; i < argNames.length; i++) {
	            visitVarInsn(ALOAD, 0);
	            visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
	        }
	
	        // 转换参数类型以匹配实现方法的期望类型
	        convertArgumentTypes(methodType);
	
	        // 调用目标方法
	        visitMethodInsn(invocationOpcode(), implMethodClassName,
	                        implMethodName, implMethodDesc,
	                        implDefiningClass.isInterface());
	
	        // 转换返回值类型(如果有)并返回
	        // 注意:如果从非void转换为void,'return'指令将弹出不需要的结果
	        Class<?> samReturnClass = methodType.returnType();
	        convertType(implMethodReturnClass, samReturnClass, samReturnClass);
	        visitInsn(getReturnOpcode(samReturnClass));
	        // Maxs由ClassWriter.COMPUTE_MAXS计算,这些参数被忽略
	        visitMaxs(-1, -1);
	        visitEnd();
		    }
		}

	
		/**
			
			convertArgumentTypes代码的作用是在生成Lambda表达式的字节码时,将SAM(Single Abstract Method,单一抽象方法)接口的参数类型转换为实现方法的参数类型。这是Lambda表达式实现的一部分,确保方法调用时参数类型匹配。
			
			### 代码解释
			
			1. **初始化变量**:
			   - `int lvIndex = 0;`:局部变量索引初始化为0。
			   - `boolean samIncludesReceiver = implIsInstanceMethod && invokedType.parameterCount() == 0;`:判断是否需要包含接收者(this),即实现方法是实例方法且调用类型参数数量为0。
			   - `int samReceiverLength = samIncludesReceiver ? 1 : 0;`:如果包含接收者,则接收者长度为1,否则为0。
			
			2. **处理接收者**:
			   如果`samIncludesReceiver`为`true`,则需要处理接收者:
			   - 通过`Class<?> rcvrType = samType.parameterType(0);`获取接收者的类型。
			   - 使用`visitVarInsn(getLoadOpcode(rcvrType), lvIndex + 1);`将接收者加载到栈顶。
			   - `lvIndex += getParameterSize(rcvrType);`更新局部变量索引。
			   - `convertType(rcvrType, implDefiningClass, instantiatedMethodType.parameterType(0));`将接收者类型转换为实现方法定义的类型。
			
			3. **处理SAM接口的参数**:
			   - `int samParametersLength = samType.parameterCount();`获取SAM接口参数的数量。
			   - `int argOffset = implMethodType.parameterCount() - samParametersLength;`计算实现方法参数与SAM接口参数的偏移量。
			   - 循环遍历SAM接口的参数:
			     - `Class<?> argType = samType.parameterType(i);`获取当前参数的类型。
			     - `visitVarInsn(getLoadOpcode(argType), lvIndex + 1);`将参数加载到栈顶。
			     - `lvIndex += getParameterSize(argType);`更新局部变量索引。
			     - `convertType(argType, implMethodType.parameterType(argOffset + i), instantiatedMethodType.parameterType(i));`将参数类型转换为实现方法的参数类型。
			
			### 关键函数和变量解释
			
			- `implIsInstanceMethod`:表示实现方法是否为实例方法。
			- `invokedType`:调用类型,Lambda表达式的目标类型。
			- `samType`:SAM接口的方法类型。
			- `implDefiningClass`:实现方法所在的类。
			- `instantiatedMethodType`:实例化方法的类型。
			- `implMethodType`:实现方法的类型。
			- `getLoadOpcode(Class<?> c)`:根据参数类型获取相应的加载指令。
			- `getParameterSize(Class<?> c)`:获取参数所占的大小,用于更新局部变量索引。
			- `convertType(Class<?> src, Class<?> dst, Class<?> bridgeType)`:将源类型转换为目标类型,可能涉及到类型的自动装箱或拆箱。
			
			这段代码是Lambda表达式实现的关键部分,确保了类型安全的方法调用,通过动态生成的字节码来实现Lambda表达式的功能。
		*/
		private void convertArgumentTypes(MethodType samType) {
		    int lvIndex = 0;
		    // 判断是否为实例方法且调用类型参数数量为0
		    boolean samIncludesReceiver = implIsInstanceMethod &&
		                                           invokedType.parameterCount() == 0;
		    // 如果包含接收者,则长度为1,否则为0
		    int samReceiverLength = samIncludesReceiver ? 1 : 0;
		    if (samIncludesReceiver) {
		        // 如果包含接收者,加载接收者参数
		        Class<?> rcvrType = samType.parameterType(0);
		        visitVarInsn(getLoadOpcode(rcvrType), lvIndex + 1);
		        lvIndex += getParameterSize(rcvrType);
		        // 转换接收者类型
		        convertType(rcvrType, implDefiningClass, instantiatedMethodType.parameterType(0));
		    }
		    // 获取SAM类型的参数数量
		    int samParametersLength = samType.parameterCount();
		    // 计算实现方法类型参数与SAM类型参数的偏移量
		    int argOffset = implMethodType.parameterCount() - samParametersLength;
		    for (int i = samReceiverLength; i < samParametersLength; i++) {
		        // 加载SAM类型的参数
		        Class<?> argType = samType.parameterType(i);
		        visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
		        lvIndex += getParameterSize(argType);
		        // 转换参数类型
		        convertType(argType, implMethodType.parameterType(argOffset + i), instantiatedMethodType.parameterType(i));
		    }
		}
		/**
		 * 根据实现方法的类型返回相应的字节码指令操作码。
		 * 
		 * @return int 返回对应的字节码指令操作码。
		 * @throws InternalError 如果遇到未预期的实现方法类型,则抛出内部错误。
		 */
		private int invocationOpcode() throws InternalError {
		    switch (implKind) {
		        case MethodHandleInfo.REF_invokeStatic:
		            return INVOKESTATIC; // 静态方法调用
		        case MethodHandleInfo.REF_newInvokeSpecial:
		            return INVOKESPECIAL; // 特殊构造方法调用
		         case MethodHandleInfo.REF_invokeVirtual:
		            return INVOKEVIRTUAL; // 虚方法调用
		        case MethodHandleInfo.REF_invokeInterface:
		            return INVOKEINTERFACE; // 接口方法调用
		        case MethodHandleInfo.REF_invokeSpecial:
		            return INVOKESPECIAL; // 特殊方法调用,如私有方法、实例初始化方法等
		        default:
		            throw new InternalError("Unexpected invocation kind: " + implKind); // 遇到未知的调用类型,抛出错误
		    }
		}
	
	}

	/**
	 * 获取参数类型所占的槽位大小
	 * @param c 参数的类对象
	 * @return 参数所占的槽位数
	 */
	static int getParameterSize(Class<?> c) {
	    if (c == Void.TYPE) {
	        return 0; // Void类型不占槽位
	    } else if (c == Long.TYPE || c == Double.TYPE) {
	        return 2; // Long和Double类型占两个槽位
	    }
	    return 1; // 其他类型占一个槽位
	}
	
	/**
	 * 根据类类型获取对应的加载指令操作码
	 * @param c 类对象
	 * @return 加载指令的操作码
	 */
	static int getLoadOpcode(Class<?> c) {
	    if(c == Void.TYPE) {
	        throw new InternalError("Unexpected void type of load opcode"); // Void类型不应该加载
	    }
	    return ILOAD + getOpcodeOffset(c); // 根据类型偏移获取具体的加载指令
	}
	
	/**
	 * 根据类类型获取对应的返回指令操作码
	 * @param c 类对象
	 * @return 返回指令的操作码
	 */
	static int getReturnOpcode(Class<?> c) {
	    if(c == Void.TYPE) {
	        return RETURN; // Void类型使用RETURN指令
	    }
	    return IRETURN + getOpcodeOffset(c); // 根据类型偏移获取具体的返回指令
	}
	
	/**
	 * 获取基本类型对应的操作码偏移量
	 * @param c 类对象
	 * @return 操作码的偏移量
	 */
	private static int getOpcodeOffset(Class<?> c) {
	    if (c.isPrimitive()) {
	        if (c == Long.TYPE) {
	            return 1; // Long类型偏移量为1
	        } else if (c == Float.TYPE) {
	            return 2; // Float类型偏移量为2
	        } else if (c == Double.TYPE) {
	            return 3; // Double类型偏移量为3
	        }
	        return 0; // 其他基本类型偏移量为0
	    } else {
	        return 4; // 引用类型偏移量为4
	    }
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值