LambdaGenerator.java
package com.alibaba.fastjson2.benchmark;
import com.alibaba.fastjson2.internal.asm.ASMUtils;
import com.alibaba.fastjson2.internal.asm.ClassWriter;
import com.alibaba.fastjson2.internal.asm.MethodWriter;
import com.alibaba.fastjson2.internal.asm.Opcodes;
import com.alibaba.fastjson2.util.DynamicClassLoader;
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.ObjIntConsumer;
public class LambdaGenerator {
static final AtomicInteger counter = new AtomicInteger();
public static <T> ObjIntConsumer<T> createSetterInt(Class<T> objectClass, String methodName) throws Throwable {
ClassWriter cw = new ClassWriter(null);
final String JAVA_LANG_OBJECT = "java/lang/Object";
String[] interfaces = {"java/util/function/ObjIntConsumer"};
String lambdaClassName = "SetInt$Lambda$" + counter.incrementAndGet();
// if (JDKUtils.JVM_VERSION > 16) {
// String pkgName = objectClass.getPackage().getName();
// pkgName = pkgName.replace('.', '/');
// lambdaClassName = pkgName + '/' + lambdaClassName;
// }
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, lambdaClassName, JAVA_LANG_OBJECT, interfaces);
final int THIS = 0;
{
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"<init>",
"()V",
64
);
mw.visitVarInsn(Opcodes.ALOAD, THIS);
mw.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mw.visitInsn(Opcodes.RETURN);
mw.visitMaxs(3, 3);
}
MethodWriter mw = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"accept",
"(Ljava/lang/Object;I)V",
64
);
String TYPE_OBJECT = ASMUtils.type(objectClass);
int OBJECT = 1, VALUE = 2;
mw.visitVarInsn(Opcodes.ALOAD, OBJECT);
mw.visitTypeInsn(Opcodes.CHECKCAST, TYPE_OBJECT);
mw.visitVarInsn(Opcodes.ILOAD, VALUE);
Class returnType = Void.TYPE;
String methodDesc;
if (returnType == Void.TYPE) {
methodDesc = "(I)V";
} else {
methodDesc = "(I)" + ASMUtils.desc(returnType);
}
mw.visitMethodInsn(Opcodes.INVOKEVIRTUAL, TYPE_OBJECT, methodName, methodDesc, false);
if (returnType != Void.TYPE) {
mw.visitInsn(Opcodes.POP);
}
mw.visitInsn(Opcodes.RETURN);
mw.visitMaxs(2, 2);
byte[] code = cw.toByteArray();
Class functionClass = DynamicClassLoader.getInstance().defineClassPublic(lambdaClassName, code, 0, code.length);
Constructor ctr = functionClass.getDeclaredConstructor();
Object inst = ctr.newInstance();
ConstantCallSite callSite = new ConstantCallSite(MethodHandles.constant(ObjIntConsumer.class, inst));
return (ObjIntConsumer<T>) callSite.getTarget().invokeExact();
}
}