Example usage for org.objectweb.asm Opcodes INVOKESPECIAL

List of usage examples for org.objectweb.asm Opcodes INVOKESPECIAL

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes INVOKESPECIAL.

Prototype

int INVOKESPECIAL

To view the source code for org.objectweb.asm Opcodes INVOKESPECIAL.

Click Source Link

Usage

From source file:com.devexperts.aprof.transformer.AbstractMethodVisitor.java

License:Open Source License

@Override
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc,
        boolean intf) {
    if (context.isInternalLocation()) {
        // do not instrument method invocations in internal locations
        mv.visitMethodInsn(opcode, owner, name, desc, intf);
        return;/*from   ww w  .ja va2s.  co  m*/
    }

    String cname = owner.replace('/', '.'); // convert owner to dot-separated class name

    // check if it is eligible object.clone call (that can get dispatched to actual Object.clone method
    boolean isClone = opcode != Opcodes.INVOKESTATIC && name.equals(TransformerUtil.CLONE)
            && desc.equals(TransformerUtil.NOARG_RETURNS_OBJECT);
    boolean isArrayClone = isClone && owner.startsWith("[");
    boolean isObjectClone = isClone && AProfRegistry.isDirectCloneClass(cname);

    if (context.isMethodInvocationTracked(cname, opcode, owner, name, desc)) {
        visitTrackedMethodInsn(opcode, owner, name, desc, intf);
    } else {
        mv.visitMethodInsn(opcode, owner, name, desc, intf);
    }

    if (!context.getConfig().isReflect())
        return;
    if (context.isIntrinsicArraysCopyOf())
        return;

    if (opcode == Opcodes.INVOKEVIRTUAL && isObjectClone) {
        // INVOKEVIRTUAL needs runtime check of class that is being cloned
        visitAllocateReflectVClone();
        return;
    }

    if (opcode == Opcodes.INVOKESPECIAL && isObjectClone) {
        // Object.clone via super.clone (does not need runtime check)
        visitAllocateReflect(true);
        return;
    }

    if (isArrayClone) {
        // <array>.clone (usually via INVOKEVIRTUAL, but we don't care)
        visitAllocateReflect(false);
        return;
    }

    if (opcode == Opcodes.INVOKESTATIC && owner.equals("java/lang/reflect/Array") && name.equals("newInstance")
            && (desc.equals(TransformerUtil.CLASS_INT_RETURNS_OBJECT)
                    || desc.equals(TransformerUtil.CLASS_INT_ARR_RETURNS_OBJECT))) {
        // Array.newInstance
        visitAllocateReflect(false);
        return;
    }

    if (opcode == Opcodes.INVOKESTATIC && TransformerUtil.isIntrinsicArraysCopyOf(owner, name, desc)) {
        // HotSpot intrinsic for Arrays.copyOf and Arrays.copyOfRange
        visitAllocateReflect(false);
    }
}

From source file:com.dragome.callbackevictor.serverside.bytecode.transformation.asm.ContinuationMethodAnalyzer.java

License:Apache License

boolean needsFrameGuard(int opcode, String owner, String name, String desc) {
    /* TODO: need to customize a way enchancer skips classes/methods
        if (owner.startsWith("java/")) {
     System.out.println("SKIP:: " + owner + "." + name + desc);
     return false;/*from  w  w  w.  j  a v  a  2  s.c  o  m*/
        }
    */

    if (opcode == Opcodes.INVOKEINTERFACE || (opcode == Opcodes.INVOKESPECIAL && !"<init>".equals(name))
            || opcode == Opcodes.INVOKESTATIC || opcode == Opcodes.INVOKEVIRTUAL) {
        return true;
    }
    return false;
}

From source file:com.e2info.helloasm.HelloAsmApp.java

License:Open Source License

public static void main(String[] args) throws IOException {
    String name = "HelloAsm";
    int flag = ClassWriter.COMPUTE_MAXS;
    ClassWriter cw = new ClassWriter(flag);
    cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, name, null, "java/lang/Object", null);

    cw.visitSource(name + ".java", null);

    {//ww  w. j  a  v a2 s .co  m
        MethodVisitor mv;
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
        mv.visitInsn(Opcodes.RETURN);
        // we need this call to take effect ClassWriter.COMPUTE_MAXS flag.
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }

    {
        MethodVisitor mv;
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "main", "([Ljava/lang/String;)V", null,
                null);
        mv.visitCode();
        mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
        mv.visitLdcInsn("hello ASM");
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
        mv.visitInsn(Opcodes.RETURN);
        // we need this call to take effect ClassWriter.COMPUTE_MAXS flag.
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }

    cw.visitEnd();

    // build binary
    byte[] bin = cw.toByteArray();

    // save asm trace for human readable
    {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        new ClassReader(bin).accept(new TraceClassVisitor(pw), 0);
        File f = new File(name + ".txt");
        FileUtils.writeStringToFile(f, sw.toString());
    }

    // save as calss file
    {
        File f = new File(name + ".class");
        FileUtils.writeByteArrayToFile(f, bin);
    }

}

From source file:com.enea.jcarder.agent.instrument.StackAnalyzeMethodVisitor.java

License:GNU General Public License

public void visitMethodInsn(int opCode, String owner, String name, String desc) {
    mMethodVisitor.visitMethodInsn(opCode, owner, name, desc);
    switch (opCode) {
    case Opcodes.INVOKEVIRTUAL:
        // pass through to next case.
    case Opcodes.INVOKESPECIAL:
        // pass through to next case.
    case Opcodes.INVOKESTATIC:
        if ("forName".equals(name) && "java/lang/Class".equals(owner)
                && "(Ljava/lang/String;)Ljava/lang/Class;".equals(desc)) {
            Object stackObject = popObject();
            if (stackObject instanceof String) {
                String classDescription = ((String) stackObject) + ".class";
                pushTextualDescription(classDescription);
                break;
            }//w  ww .j  a v a  2  s  . c om
        }
        // pass through to next case.
    case Opcodes.INVOKEINTERFACE:
        clear();
        if (isNonVoidMethod(name, desc)) {
            pushTextualDescription(owner + "." + name + "()");
        }
        break;
    default:
        clear();
    }
}

From source file:com.gargoylesoftware.js.nashorn.internal.codegen.CompilerConstants.java

License:Open Source License

/**
 * Create a call representing an invokespecial to a given method. Don't
 * attempt to look this up at compile time
 *
 * @param className the class name/*  ww  w.  j  ava 2  s.  c o  m*/
 * @param name      the method name
 * @param desc      the descriptor
 *
 * @return Call representing specified invokespecial call
 */
public static Call specialCallNoLookup(final String className, final String name, final String desc) {
    return new Call(null, className, name, desc) {
        @Override
        MethodEmitter invoke(final MethodEmitter method) {
            return method.invokespecial(className, name, descriptor);
        }

        @Override
        public void invoke(final MethodVisitor mv) {
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, name, desc, false);
        }
    };
}

From source file:com.gargoylesoftware.js.nashorn.internal.codegen.CompilerConstants.java

License:Open Source License

/**
 * Create a special call, given an explicit lookup, looking up the method handle for it at the same time.
 * clazz is used as this class/*from  w  w  w  .ja  v a2s. c  om*/
 *
 * @param lookup    the lookup
 * @param clazz     the class
 * @param name      the name of the method
 * @param rtype     the return type
 * @param ptypes    the parameter types
 *
 * @return the call object representing the virtual call
 */
public static Call specialCall(final MethodHandles.Lookup lookup, final Class<?> clazz, final String name,
        final Class<?> rtype, final Class<?>... ptypes) {
    return new Call(MH.findSpecial(lookup, clazz, name, MH.type(rtype, ptypes), clazz), className(clazz), name,
            methodDescriptor(rtype, ptypes)) {
        @Override
        MethodEmitter invoke(final MethodEmitter method) {
            return method.invokespecial(className, name, descriptor);
        }

        @Override
        public void invoke(final MethodVisitor mv) {
            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, name, descriptor, false);
        }
    };
}

From source file:com.github.anba.es6draft.compiler.assembler.InstructionAssembler.java

License:Open Source License

public void invokespecial(Type owner, String name, MethodTypeDescriptor desc, boolean itf) {
    methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, owner.internalName(), name, desc.descriptor(), itf);
    stack.invokespecial(desc);/*from   w  ww .j  av  a  2s  . co m*/
}

From source file:com.github.antag99.retinazer.weaver.MapperGenerator.java

License:Open Source License

@Override
public void accept(ClassVisitor visitor) {
    visitor.visit(V1_7, ACC_PUBLIC + ACC_FINAL + ACC_SYNTHETIC, metadata.getMapperName(),
            "Lcom/github/antag99/retinazer/PackedMapper<L" + metadata.getMapperName() + ";>;",
            "com/github/antag99/retinazer/PackedMapper", null);
    for (ComponentProperty property : metadata.properties) {
        FieldVisitor propertyField = visitor.visitField(ACC_PRIVATE + ACC_FINAL, property.getMetadataName(),
                property.getMetadataDesc(), null, null);
        if (propertyField != null)
            propertyField.visitEnd();//from   w w w  .jav a2 s.  com
    }

    FieldVisitor flyweightField = visitor.visitField(ACC_PRIVATE + ACC_FINAL, "flyweight",
            "L" + metadata.internalName + ";", null, null);
    if (flyweightField != null)
        flyweightField.visitEnd();

    // @off: Formatter mangles the elegant method syntax

    new MethodVisitor(ASM5, visitor.visitMethod(ACC_PUBLIC, "<init>",
            "(Lcom/github/antag99/retinazer/Engine;I)V", null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitVarInsn(ALOAD, 1);
            visitLdcInsn(Type.getObjectType(metadata.internalName));
            visitVarInsn(ILOAD, 2);
            visitMethodInsn(Opcodes.INVOKESPECIAL, "com/github/antag99/retinazer/PackedMapper", "<init>",
                    "(Lcom/github/antag99/retinazer/Engine;Ljava/lang/Class;I)V", false);

            for (ComponentProperty property : metadata.properties) {
                visitVarInsn(ALOAD, 0);
                visitTypeInsn(NEW, WeaverConstants.getMetadataName(property.type));
                visitInsn(Opcodes.DUP);
                visitLdcInsn(property.name);
                if (property.type.getSort() == Type.OBJECT) {
                    visitLdcInsn(property.type);
                    visitMethodInsn(INVOKESPECIAL, WeaverConstants.getMetadataName(property.type), "<init>",
                            "(Ljava/lang/String;Ljava/lang/Class;)V", false);
                } else {
                    visitMethodInsn(INVOKESPECIAL, WeaverConstants.getMetadataName(property.type), "<init>",
                            "(Ljava/lang/String;)V", false);
                }
                visitFieldInsn(PUTFIELD, metadata.getMapperName(), property.getMetadataName(),
                        property.getMetadataDesc());
            }

            visitVarInsn(ALOAD, 0);
            visitInsn(DUP);
            visitMethodInsn(INVOKEVIRTUAL, metadata.getMapperName(), "createFlyweight",
                    "()L" + metadata.internalName + ";", false);
            visitFieldInsn(PUTFIELD, metadata.getMapperName(), "flyweight", "L" + metadata.internalName + ";");
            visitInsn(RETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5, visitor.visitMethod(ACC_PUBLIC, "createFlyweight",
            "()L" + metadata.internalName + ";", null, null)) {
        {
            visitCode();
            visitTypeInsn(NEW, metadata.internalName);
            visitInsn(DUP);
            visitMethodInsn(INVOKESPECIAL, metadata.internalName, "<init>", "()V", false);

            for (ComponentProperty property : metadata.properties) {
                visitInsn(DUP);
                visitVarInsn(ALOAD, 0);
                visitFieldInsn(GETFIELD, metadata.getMapperName(), property.getMetadataName(),
                        property.getMetadataDesc());
                visitMethodInsn(INVOKEVIRTUAL, WeaverConstants.getMetadataName(property.type), "getBag",
                        "()" + property.getBagDesc(), false);
                visitFieldInsn(PUTFIELD, metadata.internalName, property.getBagName(), property.getBagDesc());
            }

            visitInsn(ARETURN);

            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5,
            visitor.visitMethod(ACC_PUBLIC, "create", "(I)L" + metadata.internalName + ";", null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitVarInsn(ILOAD, 1);
            visitMethodInsn(INVOKEVIRTUAL, "com/github/antag99/retinazer/Mapper", "checkCreate", "(I)V", false);
            visitVarInsn(ALOAD, 0);
            visitVarInsn(ILOAD, 1);
            visitMethodInsn(INVOKEVIRTUAL, metadata.getMapperName(), "get",
                    "(I)L" + metadata.internalName + ";", false);
            visitInsn(DUP);
            visitMethodInsn(INVOKEVIRTUAL, metadata.internalName, WeaverConstants.RESET_METHOD_NAME,
                    WeaverConstants.RESET_METHOD_DESC, false);
            visitInsn(ARETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5, visitor.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC + ACC_BRIDGE, "create",
            "(I)Lcom/github/antag99/retinazer/Component;", null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitVarInsn(ILOAD, 1);
            visitMethodInsn(INVOKEVIRTUAL, metadata.getMapperName(), "create",
                    "(I)L" + metadata.internalName + ";", false);
            visitInsn(ARETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5,
            visitor.visitMethod(ACC_PUBLIC, "get", "(I)L" + metadata.internalName + ";", null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitFieldInsn(GETFIELD, metadata.getMapperName(), "flyweight", "L" + metadata.internalName + ";");
            visitInsn(DUP);
            visitVarInsn(ILOAD, 1);
            visitFieldInsn(PUTFIELD, metadata.internalName, WeaverConstants.INDEX_FIELD_NAME,
                    WeaverConstants.INDEX_FIELD_DESC);
            visitInsn(ARETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5, visitor.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "get",
            "(I)Lcom/github/antag99/retinazer/Component;", null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitVarInsn(ILOAD, 1);
            visitMethodInsn(INVOKEVIRTUAL, metadata.getMapperName(), "get",
                    "(I)L" + metadata.internalName + ";", false);
            visitInsn(ARETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5, visitor.visitMethod(ACC_PUBLIC, "getProperties",
            "()[Lcom/github/antag99/retinazer/util/Property;", null, null)) {
        {
            visitCode();
            visitLdcInsn(metadata.properties.size());
            visitTypeInsn(ANEWARRAY, "com/github/antag99/retinazer/util/Property");

            List<ComponentProperty> properties = metadata.properties;
            for (int i = 0, n = properties.size(); i < n; i++) {
                ComponentProperty property = properties.get(i);
                visitInsn(DUP);
                visitLdcInsn(i);
                visitVarInsn(ALOAD, 0);
                visitFieldInsn(GETFIELD, metadata.getMapperName(), property.getMetadataName(),
                        property.getMetadataDesc());
                visitInsn(AASTORE);
            }

            visitInsn(ARETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    new MethodVisitor(ASM5, visitor.visitMethod(ACC_PUBLIC, "applyComponentChanges", "()V", null, null)) {
        {
            visitCode();
            visitVarInsn(ALOAD, 0);
            visitFieldInsn(GETFIELD, "com/github/antag99/retinazer/Mapper", "componentsMask",
                    "Lcom/github/antag99/retinazer/util/Mask;");
            visitVarInsn(ASTORE, 1);
            visitVarInsn(ALOAD, 0);
            visitFieldInsn(GETFIELD, "com/github/antag99/retinazer/Mapper", "removeMask",
                    "Lcom/github/antag99/retinazer/util/Mask;");
            visitVarInsn(ASTORE, 2);
            for (ComponentProperty property : metadata.properties) {
                visitVarInsn(ALOAD, 0);
                visitFieldInsn(GETFIELD, metadata.getMapperName(), property.getMetadataName(),
                        property.getMetadataDesc());
                visitMethodInsn(INVOKEVIRTUAL, WeaverConstants.getMetadataName(property.type), "getBag",
                        "()" + property.getBagDesc(), false);
                visitVarInsn(ALOAD, 2);
                visitMethodInsn(INVOKEVIRTUAL, WeaverConstants.getBagName(property.type), "clear",
                        "(Lcom/github/antag99/retinazer/util/Mask;)V", false);
            }
            visitVarInsn(ALOAD, 1);
            visitVarInsn(ALOAD, 2);
            visitMethodInsn(INVOKEVIRTUAL, "com/github/antag99/retinazer/util/Mask", "andNot",
                    "(Lcom/github/antag99/retinazer/util/Mask;)V", false);
            visitInsn(RETURN);
            visitMaxs(0, 0);
            visitEnd();
        }
    };

    visitor.visitEnd();
}

From source file:com.github.fge.grappa.misc.AsmUtils.java

License:Open Source License

public static boolean isVarRoot(AbstractInsnNode insn) {
    Objects.requireNonNull(insn, "insn");
    boolean r = false;
    if (insn.getOpcode() == Opcodes.INVOKESPECIAL) {
        MethodInsnNode mi = (MethodInsnNode) insn;
        r = isVarRoot(mi.owner, mi.name, mi.desc);
    }/*ww w. j a  v a2 s.  co m*/
    return r;
}

From source file:com.github.malamut2.low.AllocationMethodAdapter.java

License:Apache License

/**
 * 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.
 *///  www  .  j a  v  a2s  .c  om
@Override
public void visitMethodInsn(int opcode, String owner, String name, String signature, boolean itf) {
    if (opcode == Opcodes.INVOKESTATIC &&
    // Array does its own native allocation.  Grr.
            owner.equals("java/lang/reflect/Array") && name.equals("newInstance")) {
        if (signature.equals("(Ljava/lang/Class;I)Ljava/lang/Object;")) {

            Label beginScopeLabel = new Label();
            Label endScopeLabel = new Label();
            super.visitLabel(beginScopeLabel);

            // stack: ... class count
            int countIndex = newLocal("I", beginScopeLabel, endScopeLabel);
            super.visitVarInsn(Opcodes.ISTORE, countIndex);
            // -> stack: ... class
            pushClassNameOnStack();
            // -> stack: ... class className
            int typeNameIndex = newLocal("Ljava/lang/String;", beginScopeLabel, endScopeLabel);
            super.visitVarInsn(Opcodes.ASTORE, typeNameIndex);
            // -> stack: ... class
            super.visitVarInsn(Opcodes.ILOAD, countIndex);
            // -> stack: ... class count
            super.visitMethodInsn(opcode, owner, name, signature, itf);
            // -> stack: ... newobj
            super.visitInsn(Opcodes.DUP);
            // -> stack: ... newobj newobj
            super.visitVarInsn(Opcodes.ILOAD, countIndex);
            // -> stack: ... newobj newobj count
            super.visitInsn(Opcodes.SWAP);
            // -> stack: ... newobj count newobj
            super.visitVarInsn(Opcodes.ALOAD, typeNameIndex);
            super.visitLabel(endScopeLabel);
            // -> stack: ... newobj count newobj className
            super.visitInsn(Opcodes.SWAP);
            // -> stack: ... newobj count className newobj
            super.visitMethodInsn(Opcodes.INVOKESTATIC, recorderClass, recorderMethod, RECORDER_SIGNATURE,
                    false);
            // -> stack: ... newobj
            return;
        } else if (signature.equals("(Ljava/lang/Class;[I)Ljava/lang/Object;")) {
            Label beginScopeLabel = new Label();
            Label endScopeLabel = new Label();
            super.visitLabel(beginScopeLabel);

            int dimsArrayIndex = newLocal("[I", beginScopeLabel, endScopeLabel);
            // stack: ... class dimsArray
            pushProductOfIntArrayOnStack();
            // -> stack: ... class dimsArray product
            int productIndex = newLocal("I", beginScopeLabel, endScopeLabel);
            super.visitVarInsn(Opcodes.ISTORE, productIndex);
            // -> stack: ... class dimsArray

            super.visitVarInsn(Opcodes.ASTORE, dimsArrayIndex);
            // -> stack: ... class
            pushClassNameOnStack();
            // -> stack: ... class className
            int typeNameIndex = newLocal("Ljava/lang/String;", beginScopeLabel, endScopeLabel);
            super.visitVarInsn(Opcodes.ASTORE, typeNameIndex);
            // -> stack: ... class
            super.visitVarInsn(Opcodes.ALOAD, dimsArrayIndex);
            // -> stack: ... class dimsArray
            super.visitMethodInsn(opcode, owner, name, signature, itf);
            // -> stack: ... newobj

            super.visitInsn(Opcodes.DUP);
            // -> stack: ... newobj newobj
            super.visitVarInsn(Opcodes.ILOAD, productIndex);
            // -> stack: ... newobj newobj product
            super.visitInsn(Opcodes.SWAP);
            // -> stack: ... newobj product newobj
            super.visitVarInsn(Opcodes.ALOAD, typeNameIndex);
            super.visitLabel(endScopeLabel);
            // -> stack: ... newobj product newobj className
            super.visitInsn(Opcodes.SWAP);
            // -> stack: ... newobj product className newobj
            super.visitMethodInsn(Opcodes.INVOKESTATIC, recorderClass, recorderMethod, RECORDER_SIGNATURE,
                    false);
            // -> stack: ... newobj
            return;
        }
    }

    if (opcode == Opcodes.INVOKEVIRTUAL) {
        if ("clone".equals(name) && owner.startsWith("[")) {
            super.visitMethodInsn(opcode, owner, name, signature, itf);

            int i = 0;
            while (i < owner.length()) {
                if (owner.charAt(i) != '[') {
                    break;
                }
                i++;
            }
            if (i > 1) {
                // -> stack: ... newobj
                super.visitTypeInsn(Opcodes.CHECKCAST, owner);
                // -> stack: ... arrayref
                calculateArrayLengthAndDispatch(owner.substring(i), i);
            } else {
                // -> stack: ... newobj
                super.visitInsn(Opcodes.DUP);
                // -> stack: ... newobj newobj
                super.visitTypeInsn(Opcodes.CHECKCAST, owner);
                // -> stack: ... newobj arrayref
                super.visitInsn(Opcodes.ARRAYLENGTH);
                // -> stack: ... newobj length
                super.visitInsn(Opcodes.SWAP);
                // -> stack: ... length newobj
                invokeRecordAllocation(owner.substring(i));
            }
            return;
        }
    }

    if (opcode == Opcodes.INVOKESPECIAL) {
        if (!"clone".equals(name) || !"java/lang/Object".equals(owner)) {
            if ("<init>".equals(name) && outstandingAllocs > 0) {
                // Tricky because superclass initializers mean there can be more calls
                // to <init> than calls to NEW; hence outstandingAllocs.
                --outstandingAllocs;

                // Most of the time (i.e. in bytecode generated by javac) it is the case
                // that following an <init> call the top of the stack has a reference ot
                // the newly-initialized object.  But nothing in the JVM Spec requires
                // this, so we need to play games with the stack to make an explicit
                // extra copy (and then discard it).

                dupStackElementBeforeSignatureArgs(signature);
                super.visitMethodInsn(opcode, owner, name, signature, itf);
                super.visitLdcInsn(-1);
                super.visitInsn(Opcodes.SWAP);
                invokeRecordAllocation(owner);
                super.visitInsn(Opcodes.POP);
                return;
            }
        }
    }

    super.visitMethodInsn(opcode, owner, name, signature, itf);

}