下面列出了怎么用org.objectweb.asm.Handle的API类实例代码及写法,或者点击链接到github查看源代码。
default Object[] createBootstrapMethodArguments(String abstractMethodDesc, int insn, ClassNode methodOwnerClassNode, MethodNode methodNode, boolean serializable) {
Parameter[] parameters = methodNode.getNodeMetaData(ORIGINAL_PARAMETERS_WITH_EXACT_TYPE);
List<Object> argumentList = new LinkedList<>();
argumentList.add(Type.getType(abstractMethodDesc));
argumentList.add(
new Handle(
insn,
BytecodeHelper.getClassInternalName(methodOwnerClassNode.getName()),
methodNode.getName(),
BytecodeHelper.getMethodDescriptor(methodNode),
methodOwnerClassNode.isInterface()
)
);
argumentList.add(Type.getType(BytecodeHelper.getMethodDescriptor(methodNode.getReturnType(), parameters)));
if (serializable) {
argumentList.add(5);
argumentList.add(0);
}
return argumentList.toArray();
}
@Override
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
/*
* Track where lambda expressions are defined.
*/
if (instrumentationActions.anyLambdaMarkedForTracking()) {
if ("java/lang/invoke/LambdaMetafactory".equals(bsm.getOwner()) && bsmArgs[1] instanceof Handle) {
Handle handle = (Handle)bsmArgs[1];
if (handle.getName().startsWith("lambda$")) {
instrumentToTrackLambdaDefinition(handle.getName(), lineNumber);
}
}
}
super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
}
private void invokeDynamicOnLambda(MethodVisitor mv, AbstractInsnNode ain) {
InvokeDynamicInsnNode indy = (InvokeDynamicInsnNode)ain;
Object[]bsmArgs = indy.bsmArgs;
// Is it a lambda conversion
if (indy.bsm.getOwner().equals("java/lang/invoke/LambdaMetafactory")) {
Handle lambdaBody = (Handle)bsmArgs[1];
Detector detector = this.methodFlow.detector();
String desc = lambdaBody.getDesc();
//if (detector.isPausable(lambdaBody.getOwner(), lambdaBody.getName(), desc)) {
//if(!lambdaBody.getName().equals("<init>")) {
bsmArgs[0] = addFiberType((org.objectweb.asm.Type)bsmArgs[0]);
bsmArgs[1] = new Handle(lambdaBody.getTag(),
lambdaBody.getOwner(),
lambdaBody.getName(),
desc.replace(")", D_FIBER + ")"));
bsmArgs[2] = addFiberType((org.objectweb.asm.Type)bsmArgs[2]);
//}
//}
}
ain.accept(mv);
}
private Executable findTargetMethod(Handle invokedMethod) throws ClassNotFoundException {
Type descriptor = Type.getMethodType(invokedMethod.getDesc());
Class<?> owner = loadFromInternal(invokedMethod.getOwner());
if (invokedMethod.getTag() == Opcodes.H_NEWINVOKESPECIAL) {
for (Constructor<?> c : owner.getDeclaredConstructors()) {
if (Type.getType(c).equals(descriptor)) {
return c;
}
}
} else {
for (Method m : owner.getDeclaredMethods()) {
if (m.getName().equals(invokedMethod.getName()) && Type.getType(m).equals(descriptor)) {
return m;
}
}
}
throw new IllegalArgumentException("Referenced method not found: " + invokedMethod);
}
@Override
public void visitLdcInsn(Object cst) {
if (cst instanceof Integer) {
push(InferredType.INT);
} else if (cst instanceof Float) {
push(InferredType.FLOAT);
} else if (cst instanceof Long) {
push(InferredType.LONG);
push(InferredType.TOP);
} else if (cst instanceof Double) {
push(InferredType.DOUBLE);
push(InferredType.TOP);
} else if (cst instanceof String) {
pushDescriptor("Ljava/lang/String;");
} else if (cst instanceof Type) {
pushDescriptor(((Type) cst).getDescriptor());
} else if (cst instanceof Handle) {
pushDescriptor("Ljava/lang/invoke/MethodHandle;");
} else {
throw new RuntimeException("Cannot handle constant " + cst + " for LDC instruction");
}
super.visitLdcInsn(cst);
}
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{"visitIntInsn", new Class<?>[]{int.class, int.class}, new Object[]{0, 0}},
{"visitVarInsn", new Class<?>[]{int.class, int.class}, new Object[]{0, 0}},
{"visitTypeInsn", new Class<?>[]{int.class, String.class}, new Object[]{0, ""}},
{"visitFieldInsn", new Class<?>[]{int.class, String.class, String.class, String.class}, new Object[]{0, "", "", ""}},
{"visitMethodInsn", new Class<?>[]{int.class, String.class, String.class, String.class, boolean.class}, new Object[]{0, "", "", "", false}},
{"visitInvokeDynamicInsn", new Class<?>[]{String.class, String.class, Handle.class, Object[].class}, new Object[]{"", "", new Handle(0, "", "", "", false), new Object[0]}},
{"visitJumpInsn", new Class<?>[]{int.class, Label.class}, new Object[]{0, new Label()}},
{"visitLdcInsn", new Class<?>[]{Object.class}, new Object[]{new Object()}},
{"visitIincInsn", new Class<?>[]{int.class, int.class}, new Object[]{0, 0}},
{"visitTableSwitchInsn", new Class<?>[]{int.class, int.class, Label.class, Label[].class}, new Object[]{0, 0, new Label(), new Label[0]}},
{"visitLookupSwitchInsn", new Class<?>[]{Label.class, int[].class, Label[].class}, new Object[]{new Label(), new int[0], new Label[0]}},
{"visitMultiANewArrayInsn", new Class<?>[]{String.class, int.class}, new Object[]{"", 0}},
{"visitInsn", new Class<?>[]{int.class}, new Object[]{1}},
});
}
@Override
public void visitInvokeDynamicInsn(
final String name,
final String descriptor,
final Handle bootstrapMethodHandle,
final Object... bootstrapMethodArguments) {
checkVisitCodeCalled();
checkVisitMaxsNotCalled();
checkMethodIdentifier(version, name, "name");
checkMethodDescriptor(version, descriptor);
if (bootstrapMethodHandle.getTag() != Opcodes.H_INVOKESTATIC
&& bootstrapMethodHandle.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
throw new IllegalArgumentException("invalid handle tag " + bootstrapMethodHandle.getTag());
}
for (Object bootstrapMethodArgument : bootstrapMethodArguments) {
checkLdcConstant(bootstrapMethodArgument);
}
super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
++insnCount;
}
@Override
public void visitInvokeDynamicInsn(
final String name,
final String descriptor,
final Handle bootstrapMethodHandle,
final Object... bootstrapMethodArguments) {
Object[] remappedBootstrapMethodArguments = new Object[bootstrapMethodArguments.length];
for (int i = 0; i < bootstrapMethodArguments.length; ++i) {
remappedBootstrapMethodArguments[i] = remapper.mapValue(bootstrapMethodArguments[i]);
}
super.visitInvokeDynamicInsn(
remapper.mapInvokeDynamicMethodName(name, descriptor),
remapper.mapMethodDesc(descriptor),
(Handle) remapper.mapValue(bootstrapMethodHandle),
remappedBootstrapMethodArguments);
}
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{Opcodes.ASM6, "visitLabel", new Class<?>[]{Label.class}, new Object[]{new Label()}},
{Opcodes.ASM6, "visitFrame", new Class<?>[]{int.class, int.class, Object[].class, int.class, Object[].class}, new Object[]{0, 0, new Object[0], 0, new Object[0]}},
{Opcodes.ASM6, "visitIntInsn", new Class<?>[]{int.class, int.class}, new Object[]{0, 0}},
{Opcodes.ASM6, "visitVarInsn", new Class<?>[]{int.class, int.class}, new Object[]{0, 0}},
{Opcodes.ASM6, "visitTypeInsn", new Class<?>[]{int.class, String.class}, new Object[]{0, ""}},
{Opcodes.ASM6, "visitFieldInsn", new Class<?>[]{int.class, String.class, String.class, String.class}, new Object[]{0, "", "", ""}},
{Opcodes.ASM4, "visitMethodInsn", new Class<?>[]{int.class, String.class, String.class, String.class}, new Object[]{0, "", "", ""}},
{Opcodes.ASM6, "visitMethodInsn", new Class<?>[]{int.class, String.class, String.class, String.class, boolean.class}, new Object[]{0, "", "", "", false}},
{Opcodes.ASM6, "visitInvokeDynamicInsn", new Class<?>[]{String.class, String.class, Handle.class, Object[].class}, new Object[]{"", "", new Handle(0, "", "", "", false), new Object[0]}},
{Opcodes.ASM6, "visitJumpInsn", new Class<?>[]{int.class, Label.class}, new Object[]{0, new Label()}},
{Opcodes.ASM6, "visitLdcInsn", new Class<?>[]{Object.class}, new Object[]{new Object()}},
{Opcodes.ASM6, "visitIincInsn", new Class<?>[]{int.class, int.class}, new Object[]{0, 0}},
{Opcodes.ASM6, "visitTableSwitchInsn", new Class<?>[]{int.class, int.class, Label.class, Label[].class}, new Object[]{0, 0, new Label(), new Label[0]}},
{Opcodes.ASM6, "visitLookupSwitchInsn", new Class<?>[]{Label.class, int[].class, Label[].class}, new Object[]{new Label(), new int[0], new Label[0]}},
{Opcodes.ASM6, "visitMultiANewArrayInsn", new Class<?>[]{String.class, int.class}, new Object[]{"", 0}},
{Opcodes.ASM6, "visitInsn", new Class<?>[]{int.class}, new Object[]{0}},
});
}
Handle decodeHandle(final String val) throws SAXException {
try {
int dotIndex = val.indexOf('.');
int descIndex = val.indexOf('(', dotIndex + 1);
int tagIndex = val.lastIndexOf('(');
int itfIndex = val.indexOf(' ', tagIndex + 1);
boolean itf = itfIndex != -1;
int tag = Integer.parseInt(val.substring(tagIndex + 1, itf ? val.length() - 1 : itfIndex));
String owner = val.substring(0, dotIndex);
String name = val.substring(dotIndex + 1, descIndex);
String desc = val.substring(descIndex, tagIndex - 1);
return new Handle(tag, owner, name, desc, itf);
} catch (RuntimeException e) {
throw new SAXException("Malformed handle " + val, e);
}
}
protected Object[] findOwnerInvokeDynamic(AbstractInsnNode instruction, List<MethodNode> ownerMethods) {
if (instruction instanceof InvokeDynamicInsnNode) {
InvokeDynamicInsnNode n = (InvokeDynamicInsnNode) instruction;
Handle bsm = n.bsm;
if ("java/lang/invoke/LambdaMetafactory".equals(bsm.getOwner()) && "metafactory".equals(bsm.getName())) {
Handle method = Arrays
.stream(n.bsmArgs)
.filter(Handle.class::isInstance)
.map(Handle.class::cast)
.filter(h -> h.getOwner().equals(classNode.name) /*&& h.getName().startsWith("lambda$")*/)
.findFirst()
.orElse(null);
if (null != method) {
MethodNode targetMethodNode = getMethod(method.getName(), method.getDesc(), ownerMethods);
if (null != targetMethodNode && (targetMethodNode.access & (/*ACC_STATIC + ACC_PRIVATE +*/ ACC_SYNTHETIC)) == /*ACC_STATIC + ACC_PRIVATE + */ACC_SYNTHETIC) {
return new Object[] {method, targetMethodNode};
}
}
}
}
return null;
}
default Handle createBootstrapMethod(boolean isInterface, boolean serializable) {
if (serializable) {
return new Handle(
Opcodes.H_INVOKESTATIC,
"java/lang/invoke/LambdaMetafactory",
"altMetafactory",
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;",
isInterface
);
}
return new Handle(
Opcodes.H_INVOKESTATIC,
"java/lang/invoke/LambdaMetafactory",
"metafactory",
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
isInterface
);
}
/**
* Mutates a handle within an invoke virtual.
*/
private Handle mutateHandle(Handle handle) {
int opcode = handle.getTag();
String owner = handle.getOwner();
String name = handle.getName();
String descriptor = handle.getDesc();
if (owner.equals(expectedOwner) && opcode == Opcodes.H_INVOKEVIRTUAL) {
if (REPLACEMENTS.containsKey(name)) {
Replacement replacement = REPLACEMENTS.get(name);
if (replacement.descriptor.equals(descriptor)) {
MutationIdentifier id = context.registerMutation(factory, replacement.toString());
if (context.shouldMutate(id)) {
return new Handle(
opcode,
owner,
replacement.destinationName,
descriptor,
handle.isInterface());
}
}
}
}
return handle;
}
public CompiledLambda(
Handle lambdaAsmHandle,
ParameterizedType returnType,
List<ParameterizedType> parameterTypes)
{
this.lambdaAsmHandle = requireNonNull(lambdaAsmHandle, "lambdaMethodAsmHandle is null");
this.returnType = requireNonNull(returnType, "returnType is null");
this.parameterTypes = ImmutableList.copyOf(requireNonNull(parameterTypes, "returnType is null"));
}
void addConstant(final Object constant) {
if (constant instanceof Type) {
addType((Type) constant);
} else if (constant instanceof Handle) {
Handle handle = (Handle) constant;
addInternalType(handle.getOwner());
addMethodTypes(handle.getDesc());
}
}
public void visitInvokeDynamicInsn( String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) {
if (bootstrapMethodHandle.getOwner().equals("java/lang/invoke/LambdaMetafactory")) {
String className = descriptor.substring(descriptor.indexOf(")L") + 2, descriptor.length() - 1);
// find out the method descriptor of the method
// We expect bootstrapMethodArguments[0] to be method descriptor
// and bootstrapMethodArguments[1] to be the methods class handle
Type methodDescriptor = (Type) bootstrapMethodArguments[0];
Handle callerHandle = (Handle) bootstrapMethodArguments[1];
currentMethod.addInvocation(Opcodes.INVOKEDYNAMIC, className, name, methodDescriptor.getDescriptor());
currentMethod.addInvocation(Opcodes.INVOKEDYNAMIC, callerHandle.getOwner(), callerHandle.getName(), callerHandle.getDesc() );
}
}
@Override
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
checkStartCode();
checkEndCode();
checkMethodIdentifier(version, name, "name");
checkMethodDesc(desc);
if (bsm.getTag() != Opcodes.H_INVOKESTATIC && bsm.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
throw new IllegalArgumentException("invalid handle tag " + bsm.getTag());
}
for (int i = 0; i < bsmArgs.length; i++) {
checkLDCConstant(bsmArgs[i]);
}
super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
++insnCount;
}
@Override
public void visitLdcInsn(final Object value) {
if (api < Opcodes.ASM5
&& (value instanceof Handle
|| (value instanceof Type && ((Type) value).getSort() == Type.METHOD))) {
throw new UnsupportedOperationException("This feature requires ASM5");
}
if (api != Opcodes.ASM7 && value instanceof ConstantDynamic) {
throw new UnsupportedOperationException("This feature requires ASM7");
}
if (value instanceof Integer) {
iconst((Integer) value);
} else if (value instanceof Byte) {
iconst(((Byte) value).intValue());
} else if (value instanceof Character) {
iconst(((Character) value).charValue());
} else if (value instanceof Short) {
iconst(((Short) value).intValue());
} else if (value instanceof Boolean) {
iconst(((Boolean) value).booleanValue() ? 1 : 0);
} else if (value instanceof Float) {
fconst((Float) value);
} else if (value instanceof Long) {
lconst((Long) value);
} else if (value instanceof Double) {
dconst((Double) value);
} else if (value instanceof String) {
aconst(value);
} else if (value instanceof Type) {
tconst((Type) value);
} else if (value instanceof Handle) {
hconst((Handle) value);
} else if (value instanceof ConstantDynamic) {
cconst((ConstantDynamic) value);
} else {
throw new IllegalArgumentException();
}
}
public void visitInvokeDynamicInsn(final String name, final String descriptor, final Handle bootstrapMethodHandle, final Object... bootstrapMethodArguments) {
if(isClinit) {
hasLambdaInClinit = true;
}
me.methodsHavingInvokeDynamic.add(this.nameAndSig);
}
/**
* Returns a {@link Enum} value constant.
*
* @param enumerationDescription The enumeration value to represent.
* @return A dynamically resolved enumeration constant.
*/
public static JavaConstant ofEnumeration(EnumerationDescription enumerationDescription) {
return new Dynamic(new ConstantDynamic(enumerationDescription.getValue(),
enumerationDescription.getEnumerationType().getDescriptor(),
new Handle(Opcodes.H_INVOKESTATIC,
CONSTANT_BOOTSTRAPS,
"enumConstant",
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Enum;",
false)), enumerationDescription.getEnumerationType());
}
/**
* Returns the given value, remapped with this remapper. Possible values are {@link Boolean},
* {@link Byte}, {@link Short}, {@link Character}, {@link Integer}, {@link Long}, {@link Double},
* {@link Float}, {@link String}, {@link Type}, {@link Handle}, {@link ConstantDynamic} or arrays
* of primitive types .
*
* @param value an object. Only {@link Type}, {@link Handle} and {@link ConstantDynamic} values
* are remapped.
* @return the given value, remapped with this remapper.
*/
public Object mapValue(final Object value) {
if (value instanceof Type) {
return mapType((Type) value);
}
if (value instanceof Handle) {
Handle handle = (Handle) value;
return new Handle(
handle.getTag(),
mapType(handle.getOwner()),
mapMethodName(handle.getOwner(), handle.getName(), handle.getDesc()),
handle.getTag() <= Opcodes.H_PUTSTATIC
? mapDesc(handle.getDesc())
: mapMethodDesc(handle.getDesc()),
handle.isInterface());
}
if (value instanceof ConstantDynamic) {
ConstantDynamic constantDynamic = (ConstantDynamic) value;
int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
Object[] remappedBootstrapMethodArguments = new Object[bootstrapMethodArgumentCount];
for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
remappedBootstrapMethodArguments[i] =
mapValue(constantDynamic.getBootstrapMethodArgument(i));
}
String descriptor = constantDynamic.getDescriptor();
return new ConstantDynamic(
mapInvokeDynamicMethodName(constantDynamic.getName(), descriptor),
mapDesc(descriptor),
(Handle) mapValue(constantDynamic.getBootstrapMethod()),
remappedBootstrapMethodArguments);
}
return value;
}
@Override
public void visitInvokeDynamicInsn(
final String name,
final String descriptor,
final Handle bootstrapMethodHandle,
final Object... bootstrapMethodArguments) {
super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
if (this.locals == null) {
labels = null;
return;
}
pop(descriptor);
pushDescriptor(descriptor);
labels = null;
}
@Override
public void visitLdcInsn(final Object value) {
super.visitLdcInsn(value);
if (this.locals == null) {
labels = null;
return;
}
if (value instanceof Integer) {
push(Opcodes.INTEGER);
} else if (value instanceof Long) {
push(Opcodes.LONG);
push(Opcodes.TOP);
} else if (value instanceof Float) {
push(Opcodes.FLOAT);
} else if (value instanceof Double) {
push(Opcodes.DOUBLE);
push(Opcodes.TOP);
} else if (value instanceof String) {
push("java/lang/String");
} else if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort == Type.OBJECT || sort == Type.ARRAY) {
push("java/lang/Class");
} else if (sort == Type.METHOD) {
push("java/lang/invoke/MethodType");
} else {
throw new IllegalArgumentException();
}
} else if (value instanceof Handle) {
push("java/lang/invoke/MethodHandle");
} else if (value instanceof ConstantDynamic) {
pushDescriptor(((ConstantDynamic) value).getDescriptor());
} else {
throw new IllegalArgumentException();
}
labels = null;
}
@Override
public void visitLdcInsn(final Object value) {
if (api < Opcodes.ASM5
&& (value instanceof Handle
|| (value instanceof Type && ((Type) value).getSort() == Type.METHOD))) {
throw new UnsupportedOperationException("This feature requires ASM5");
}
if (api != Opcodes.ASM7 && value instanceof ConstantDynamic) {
throw new UnsupportedOperationException("This feature requires ASM7");
}
if (value instanceof Integer) {
iconst((Integer) value);
} else if (value instanceof Byte) {
iconst(((Byte) value).intValue());
} else if (value instanceof Character) {
iconst(((Character) value).charValue());
} else if (value instanceof Short) {
iconst(((Short) value).intValue());
} else if (value instanceof Boolean) {
iconst(((Boolean) value).booleanValue() ? 1 : 0);
} else if (value instanceof Float) {
fconst((Float) value);
} else if (value instanceof Long) {
lconst((Long) value);
} else if (value instanceof Double) {
dconst((Double) value);
} else if (value instanceof String) {
aconst(value);
} else if (value instanceof Type) {
tconst((Type) value);
} else if (value instanceof Handle) {
hconst((Handle) value);
} else if (value instanceof ConstantDynamic) {
cconst((ConstantDynamic) value);
} else {
throw new IllegalArgumentException();
}
}
void addConstant(final Object cst)
{
if (cst instanceof Type)
{
addType((Type) cst);
}
else if (cst instanceof Handle)
{
Handle h = (Handle) cst;
addInternalName(h.getOwner());
addMethodDesc(h.getDesc());
}
}
@SuppressWarnings("deprecation")
public InvokeDynamicInsnNode() {
super(Opcodes.INVOKEDYNAMIC);
name = "";
desc = "";
bsmArgs = new Object[] { Type.getType("()V"), new Handle(Opcodes.H_INVOKESTATIC, "", "", ""), Type.getType("(V") };
bsm = new Handle(Opcodes.H_INVOKESTATIC, "", "", "");
}
@Override
public void visitInvokeDynamicInsn(
final String name,
final String descriptor,
final Handle bootstrapMethodHandle,
final Object... bootstrapMethodArguments) {
instructions.add(
new InvokeDynamicInsnNode(
name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments));
}
@Override
public void visitInvokeDynamicInsn(
final String name,
final String descriptor,
final Handle bootstrapMethodHandle,
final Object... bootstrapMethodArguments) {
p.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
}
@Override
public void visitInvokeDynamicInsn(
final String name,
final String descriptor,
final Handle bootstrapMethodHandle,
final Object... bootstrapMethodArguments) {
minSize += 5;
maxSize += 5;
super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
}
/**
* Rewrites a method handle owner to this $starkoverride class and optionally change the method
* lookup in case the lambda function was an instance method.
*
* @param handle the method handle to rewrite
* @return the new method handle to use.
*/
private Handle rewriteHandleOwner(Handle handle) {
if (handle.getOwner().equals(visitedClassName)) {
// if the target lambda captured "this", it is not a static method,
// therefore, we need to change the method signature.
MethodNode lambdaMethod =
getMethodByNameInClass(
handle.getName(), handle.getDesc(), classAndInterfaceNode);
if (lambdaMethod == null) {
throw new RuntimeException(
String.format(
"Internal stark error while locating lambda %s"
+ "in class %s, please file a bug",
handle.getName(), visitedClassName));
}
// if the original method was not static, it has now been transformed into a
// a static method during instrumentation, we should therefore adapt the
// lambda signature to include the receiver as the first parameter.
String desc =
(lambdaMethod.access & Opcodes.ACC_STATIC) == 0
? "(L" + visitedClassName + ";" + handle.getDesc().substring(1)
: handle.getDesc();
return new Handle(
// no matter what the original invoke was, we now always invoke a static
// method.
Opcodes.H_INVOKESTATIC,
visitedClassName + OVERRIDE_SUFFIX,
handle.getName(),
desc,
false);
}
return handle;
}