Search code examples
javainterfacebytecodejava-bytecode-asm

ASM transformation to find concrete class type


I'm working on a project that will trace method calls from a class within a package to any other class. It's important that I can identify concrete types, and I'd prefer to have a minimum tracing overhead. There is no restrictions on when the probe is triggered; it can be before or after a method has been called.

ASM is currently used, but there is no requirement for it. The system is moving from AspectJ in order to allow dynamic attachment, so that's out.

Below is the current situation. A 'Tracer' enum/singleton receives probe(int) and handles the call. It is sufficient to find calls from concrete types to reference types.

@Override
void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
    Integer probeID = Tracer.INSTANCE.probes.createProbeIDAt(new Call(owner, name, desc))

    super.visitFieldInsn(GETSTATIC, "org/flightofstairs/honours/capture/agent/Tracer", "INSTANCE", "Lorg/flightofstairs/honours/capture/agent/Tracer;");
    super.visitLdcInsn(probeID)
    super.visitMethodInsn(INVOKEVIRTUAL, "org/flightofstairs/honours/capture/agent/Tracer", "probe", "(Ljava/lang/Integer;)V")

    super.visitMethodInsn(opcode, owner, name, desc);
}

My idea for going further is to somehow get a reference to the invoked class and call getClass() to retrieve the concrete type. This would be trivial if the stack contained the object ref on top for INVOKEINTERFACE, but any parameters to the called method are placed above it.

It wouldn't be a problem to calculate the stack position of the object reference, given that the number of parameters is known, but java offers no way to duplicate a reference from lower in the stack.

Any advice?

Cheers.


Solution

  • A solution is to record INVOKEINTERFACEs during traversal. At the end, ASMs Analyser can be used to find instructions that pushed the objectref onto the stack, and from there it's simple to add getClass() and tracing code.

    A solution is shown here. https://gist.github.com/2795738