private void buildRecorderFromObject(
      int opcode, String owner, String name, String signature, boolean itf) {
    super.visitMethodInsn(opcode, owner, name, signature, itf);
    // -> stack: ... newobj
    super.visitInsn(Opcodes.DUP);
    // -> stack: ... newobj newobj
    super.visitInsn(Opcodes.DUP);
    // -> stack: ... newobj newobj newobj
    // We could be instantiating this class or a subclass, so we
    // have to get the class the hard way.
    super.visitMethodInsn(
        Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
    // -> stack: ... newobj newobj Class
    super.visitInsn(Opcodes.SWAP);
    // -> stack: ... newobj Class newobj
    super.visitMethodInsn(
        Opcodes.INVOKESTATIC, recorderClass, recorderMethod, CLASS_RECORDER_SIG, false);
    // -> stack: ... newobj
  }
Reflection-based allocation (@see java.lang.reflect.Array#newInstance) is triggered with a
static method call (INVOKESTATIC), so we hook it here. Class initialization is triggered with a
constructor call (INVOKESPECIAL) so we hook that here too as a proxy for the new bytecode which
leaves an uninitialized object on the stack that we're not allowed to touch. {@link
java.lang.Object#clone} is also a call to INVOKESPECIAL, and is hooked here. {@link
java.lang.Class#newInstance} and {@link java.lang.reflect.Constructor#newInstance} are both
INVOKEVIRTUAL calls, so they are hooked here, as well.
src/main/java/com/google/monitoring/runtime/instrumentation/AllocationMethodAdapter.java