Skip to content

Instantly share code, notes, and snippets.

@offbynull
Created June 8, 2018 02:03
Show Gist options
  • Select an option

  • Save offbynull/ade06c33efbbb642553d5cd49ab37603 to your computer and use it in GitHub Desktop.

Select an option

Save offbynull/ade06c33efbbb642553d5cd49ab37603 to your computer and use it in GitHub Desktop.
ASM access invokedynamic bootstrap method information
import java.io.FileInputStream;
import static java.util.Arrays.asList;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
import org.objectweb.asm.tree.MethodNode;
public class AsmInvokeDynamic {
public static void main(String[] args) throws Exception {
try (FileInputStream fis = new FileInputStream("C:\\Users\\User\\eclipse-workspace\\test\\bin\\Test.class")) {
ClassReader classReader = new ClassReader(fis);
ClassNode classNode = new ClassNode();
classReader.accept(classNode, 0);
MethodNode methodNode = classNode.methods.stream()
.filter(x -> x.name.equals("val"))
.findAny().get();
AbstractInsnNode abstractInsnNode = methodNode.instructions.getFirst();
while (abstractInsnNode != null) {
if (abstractInsnNode instanceof InvokeDynamicInsnNode) {
InvokeDynamicInsnNode invokeDynamicInsnNode = (InvokeDynamicInsnNode) abstractInsnNode;
System.out.println(invokeDynamicInsnNode.name + " " + invokeDynamicInsnNode.desc);
System.out.println("bsmowner:" + invokeDynamicInsnNode.bsm.getOwner());
System.out.println("bsmname:" + invokeDynamicInsnNode.bsm.getName());
System.out.println("bsmdesc:" + invokeDynamicInsnNode.bsm.getDesc());
System.out.println(asList(invokeDynamicInsnNode.bsmArgs));
//
// Here's an example output...
//
// accept (Ljava/util/HashSet;)Ljava/util/function/Consumer;
// bsmowner:java/lang/invoke/LambdaMetafactory
// bsmname:metafactory
// bsmdesc:(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;
// [(Ljava/lang/Object;)V, java/util/HashSet.add(Ljava/lang/Object;)Z (5), (Ljava/lang/Integer;)V]
//
// Notice how the bootstrap method descriptor takes in 6 arguments but the bootstrap method arguments only supply 3.
// This is because the JVM implicitly supplies the first 3 arguments, then we supply the next 3. The following was
// lifted from https://github.com/Sable/soot/wiki/Java's-Invokedynamic...
//
// The bootstrap method receives from the virtual machine three implicit arguments, in addition to the explicit
// static arguments provided. A standard bootstrap method would start with the following argument signatures:
//
// java.lang.invoke.MethodHandles$Lookup A lookup object representing the current class context.
// java.lang.String The uninterpreted Utf8 string stated at the invokedynamic site.
// java.lang.invoke.MethodType A method type object representing the resolved method type for this
// invokedynamic site.
}
abstractInsnNode = abstractInsnNode.getNext();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment