Example usage for org.objectweb.asm.tree TryCatchBlockNode TryCatchBlockNode

List of usage examples for org.objectweb.asm.tree TryCatchBlockNode TryCatchBlockNode

Introduction

In this page you can find the example usage for org.objectweb.asm.tree TryCatchBlockNode TryCatchBlockNode.

Prototype

public TryCatchBlockNode(final LabelNode start, final LabelNode end, final LabelNode handler,
        final String type) 

Source Link

Document

Constructs a new TryCatchBlockNode .

Usage

From source file:cl.inria.stiq.instrumenter.BCIUtils.java

License:Open Source License

private static List<TryCatchBlockNode> cloneTryCatchBlocks(ClonerMap aMap, List<TryCatchBlockNode> aList) {
    List<TryCatchBlockNode> theListClone = new ArrayList<TryCatchBlockNode>();
    for (TryCatchBlockNode theNode : aList) {
        theListClone.add(new TryCatchBlockNode(aMap.get(theNode.start), aMap.get(theNode.end),
                aMap.get(theNode.handler), theNode.type));
    }/*from ww w.  java  2 s . co m*/

    return theListClone;
}

From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java

License:Open Source License

@SuppressWarnings("unchecked")
private void splitTryCatch(FrameInfo fi) {
    for (int i = 0; i < mn.tryCatchBlocks.size(); i++) {
        TryCatchBlockNode tcb = (TryCatchBlockNode) mn.tryCatchBlocks.get(i);

        int start = getLabelIdx(tcb.start);
        int end = getLabelIdx(tcb.end);

        if (start <= fi.endInstruction && end >= fi.endInstruction) {
            db.log(LogLevel.DEBUG, "Splitting try-catch in %s, block %d call at instruction %d", mn.name, i,
                    fi.endInstruction);//from w w w .jav a 2 s .c  o  m
            //System.out.println("i="+i+" start="+start+" end="+end+" split="+splitIdx+
            //        " start="+mn.instructions.get(start)+" end="+mn.instructions.get(end));

            // need to split try/catch around the suspendable call
            if (start == fi.endInstruction) {
                tcb.start = fi.createAfterLabel();
            } else {
                if (end > fi.endInstruction) {
                    TryCatchBlockNode tcb2 = new TryCatchBlockNode(fi.createAfterLabel(), tcb.end, tcb.handler,
                            tcb.type);
                    mn.tryCatchBlocks.add(i + 1, tcb2);
                }

                tcb.end = fi.createBeforeLabel();
            }
        }
    }
}

From source file:com.github.fge.grappa.transform.CodeBlock.java

License:Apache License

public CodeBlock trycatch(LabelNode scopeStart, LabelNode scopeEnd, LabelNode handler,
        @Nullable String exceptionType) {
    tryCatchBlockList.add(new TryCatchBlockNode(scopeStart, scopeEnd, handler, exceptionType));
    return this;
}

From source file:com.github.fge.grappa.transform.CodeBlock.java

License:Apache License

public CodeBlock visitTryCatchBlock(LabelNode scopeStart, LabelNode scopeEnd, LabelNode handler,
        @Nullable String exceptionType) {
    tryCatchBlockList.add(new TryCatchBlockNode(scopeStart, scopeEnd, handler, exceptionType));
    return this;
}

From source file:com.navercorp.pinpoint.profiler.instrument.ASMTryCatch.java

License:Apache License

public ASMTryCatch(final MethodNode methodNode) {
    this.methodNode = methodNode;

    final TryCatchBlockNode tryCatchBlockNode = new TryCatchBlockNode(this.startLabelNode, this.endLabelNode,
            this.endLabelNode, "java/lang/Throwable");
    if (this.methodNode.tryCatchBlocks == null) {
        this.methodNode.tryCatchBlocks = new ArrayList<TryCatchBlockNode>();
    }//from w w  w  .ja  va2 s.c o m
    this.methodNode.tryCatchBlocks.add(tryCatchBlockNode);
}

From source file:com.offbynull.coroutines.instrumenter.InvokeWithinTryCatchContinuationPointGenerator.java

License:Open Source License

private InsnList generateLoadInstructions(LabelNode continueExecLabelNode, LabelNode failedRestoreExecLabelNode,
        List<TryCatchBlockNode> tryCatchBlockNodes) {
    // tryCatchBlock() invocation further on in this method will populate TryCatchBlockNode fields
    TryCatchBlockNode newTryCatchBlockNode = new TryCatchBlockNode(null, null, null, null);
    tryCatchBlockNodes.add(newTryCatchBlockNode);

    FlowInstrumentationVariables vars = getFlowInstrumentationVariables();
    MonitorInstrumentationInstructions monInsts = getMonitorInstrumentationInstructions();

    Variable contArg = vars.getContArg();
    Variable methodStateVar = vars.getMethodStateVar();
    Variable savedLocalsVar = vars.getSavedLocalsVar();
    Variable savedStackVar = vars.getSavedStackVar();
    Variable tempObjVar = vars.getTempObjectVar();
    Variable tempObjVar2 = vars.getTempObjVar2();

    InsnList enterMonitorsInLockStateInsnList = monInsts.getEnterMonitorsInLockStateInsnList();
    InsnList exitMonitorsInLockStateInsnList = monInsts.getExitMonitorsInLockStateInsnList();

    Type invokeMethodReturnType = getReturnTypeOfInvocation(getInvokeInsnNode());
    Type returnType = getReturnType();
    int methodStackCount = getRequiredStackCountForInvocation(getInvokeInsnNode());
    Integer lineNum = getLineNumber();

    Frame<BasicValue> frame = getFrame();

    //          enterLocks(lockState);
    //          continuation.addPending(methodState); // method state should be loaded from Continuation.saved
    //              // Load up enough of the stack to invoke the method. The invocation here needs to be wrapped in a try catch because
    //              // the original invocation was within a try catch block (at least 1, maybe more). If we do get a throwable, jump
    //              // back to the area where the original invocation was and rethrow it there so the proper catch handlers can
    //              // handle it (if the handler is for the expected throwable type).
    //          restoreStackSuffix(stack, <number of items required for method invocation below>);
    //          try {
    //              <method invocation>
    //          } catch (throwable) {
    //              tempObjVar2 = throwable;
    //              restoreOperandStack(stack);
    //              restoreLocalsStack(localVars);
    //              goto restorePoint_<number>_rethrow;
    //          }
    //          if (continuation.getMode() == MODE_SAVING) {
    //              exitLocks(lockState);
    //              return <dummy>;
    //          }
    //             // At this point the invocation happened successfully, so we want to save the invocation's result, restore this
    //             // method's state, and then put the result on top of the stack as if invocation just happened. We then jump in to
    //             // the method and continue running it from the instruction after the original invocation point.
    //          tempObjVar2 = <method invocation>'s return value; // does nothing if ret type is void
    //          restoreOperandStack(stack);
    //          restoreLocalsStack(localVars);
    //          place tempObjVar2 on top of stack if not void (as if it <method invocation> were just run and returned that value)
    //          goto restorePoint_<number>_continue;

    return merge(lineNum == null ? empty() : lineNumber(lineNum),
            cloneInsnList(enterMonitorsInLockStateInsnList),
            call(CONTINUATION_ADDPENDING_METHOD, loadVar(contArg), loadVar(methodStateVar)),
            loadOperandStackSuffix(savedStackVar, tempObjVar, frame, methodStackCount),
            tryCatchBlock(newTryCatchBlockNode, null, merge(cloneInvokeNode(getInvokeInsnNode()) // invoke method
            ), merge(saveVar(tempObjVar2),
                    loadOperandStackPrefix(savedStackVar, tempObjVar, frame,
                            frame.getStackSize() - methodStackCount),
                    loadLocalVariableTable(savedLocalsVar, tempObjVar, frame),
                    jumpTo(failedRestoreExecLabelNode))),
            ifIntegersEqual(// if we're saving after invoke, return dummy value
                    call(CONTINUATION_GETMODE_METHOD, loadVar(contArg)), loadIntConst(MODE_SAVING),
                    merge(cloneInsnList(exitMonitorsInLockStateInsnList), // inserted many times, must be cloned
                            returnDummy(returnType))),
            castToObjectAndSave(invokeMethodReturnType, tempObjVar2), // save return (does nothing if invoked method returns void)
            loadOperandStackPrefix(savedStackVar, tempObjVar, frame, frame.getStackSize() - methodStackCount),
            loadLocalVariableTable(savedLocalsVar, tempObjVar, frame),
            loadAndCastToOriginal(invokeMethodReturnType, tempObjVar2), jumpTo(continueExecLabelNode));
}

From source file:com.offbynull.coroutines.instrumenter.TryCatchInvokeContinuationPoint.java

License:Open Source License

TryCatchInvokeContinuationPoint(Integer lineNumber, MethodInsnNode invokeInstruction, Frame<BasicValue> frame) {
    // lineNumber is null if it doesn't exist
    Validate.notNull(invokeInstruction);
    Validate.notNull(frame);//from  w w  w .jav a  2 s  .  c  om

    this.lineNumber = lineNumber;
    this.invokeInstruction = invokeInstruction;
    this.continueExecutionLabel = new LabelNode();
    this.exceptionExecutionLabel = new LabelNode();
    this.tryCatchBlock = new TryCatchBlockNode(null, null, null, null);
    this.frame = frame;
}

From source file:de.unisb.cs.st.javaslicer.tracer.instrumentation.IdentifiableInstrumenter.java

License:Open Source License

@SuppressWarnings("unchecked")
public void transform(final ClassNode classNode) {
    if (!this.tracer.wasRedefined(this.readClass.getName()))
        return;// ww  w.j  a va 2 s. co m
    if ((classNode.access & ACC_INTERFACE) != 0)
        return;

    // do not modify if the parent class already implements Identifiable
    // (this is the case if the parent class was redefined)
    if (this.tracer.wasRedefined(Type.getObjectType(classNode.superName).getClassName()))
        return;

    classNode.fields
            .add(new FieldNode(ACC_PRIVATE | ACC_SYNTHETIC | ACC_TRANSIENT, ID_FIELD_NAME, "J", null, null));

    classNode.interfaces.add(Type.getInternalName(Identifiable.class));

    final MethodNode getIdMethod = new MethodNode(ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC,
            "__tracing_get_object_id", "()J", null, null);
    // first, check if the id field is already set:
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new FieldInsnNode(GETFIELD, classNode.name, ID_FIELD_NAME, "J"));
    getIdMethod.instructions.add(new InsnNode(LCONST_0));
    getIdMethod.instructions.add(new InsnNode(LCMP));
    final LabelNode l0 = new LabelNode();
    getIdMethod.instructions.add(new JumpInsnNode(IFNE, l0));

    // code to be executed if it is not set:
    // synchronized, so that the id is only set once
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new InsnNode(MONITORENTER));
    // label for the try-catch block around the synchronized block
    final LabelNode l1 = new LabelNode(), l2 = new LabelNode(), l3 = new LabelNode();
    getIdMethod.tryCatchBlocks.add(new TryCatchBlockNode(l1, l2, l3, null));
    getIdMethod.instructions.add(l1);
    // recheck if the id is set:
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new FieldInsnNode(GETFIELD, classNode.name, ID_FIELD_NAME, "J"));
    getIdMethod.instructions.add(new InsnNode(LCONST_0));
    getIdMethod.instructions.add(new InsnNode(LCMP));
    getIdMethod.instructions.add(new JumpInsnNode(IFNE, l2));

    // it is still unset:
    getIdMethod.instructions.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(Tracer.class),
            "getInstance", "()L" + Type.getInternalName(Tracer.class) + ";"));
    getIdMethod.instructions.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(Tracer.class),
            "getThreadTracer", "()L" + Type.getInternalName(ThreadTracer.class) + ";"));
    getIdMethod.instructions.add(new InsnNode(DUP));
    getIdMethod.instructions.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class),
            "pauseTracing", "()V"));
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new FieldInsnNode(GETSTATIC, Type.getInternalName(ObjectIdentifier.class),
            "instance", "L" + Type.getInternalName(ObjectIdentifier.class) + ";"));
    getIdMethod.instructions.add(new InsnNode(ACONST_NULL));
    getIdMethod.instructions.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(ObjectIdentifier.class),
            "getNewId", "(Ljava/lang/Object;)J"));
    getIdMethod.instructions.add(new FieldInsnNode(PUTFIELD, classNode.name, ID_FIELD_NAME, "J"));
    getIdMethod.instructions.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class),
            "resumeTracing", "()V"));

    getIdMethod.instructions.add(l2);
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new InsnNode(MONITOREXIT));
    getIdMethod.instructions.add(new JumpInsnNode(GOTO, l0));
    getIdMethod.instructions.add(l3);
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new InsnNode(MONITOREXIT));
    getIdMethod.instructions.add(new InsnNode(ATHROW));

    getIdMethod.instructions.add(l0);
    getIdMethod.instructions.add(new VarInsnNode(ALOAD, 0));
    getIdMethod.instructions.add(new FieldInsnNode(GETFIELD, classNode.name, ID_FIELD_NAME, "J"));
    getIdMethod.instructions.add(new InsnNode(LRETURN));

    classNode.methods.add(getIdMethod);

    // now, instrument all constructors: initialize object id at the beginning of each constructor
    /*
    for (final Object methodObj: classNode.methods) {
    final MethodNode method = (MethodNode) methodObj;
    if (method.name.equals("<init>") && (method.access & ACC_ABSTRACT) == 0) {
        final InsnList newInsns = new InsnList();
        newInsns.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(Tracer.class),
                "getInstance", "()L"+Type.getInternalName(Tracer.class)+";"));
        newInsns.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(Tracer.class),
                "getThreadTracer", "()L"+Type.getInternalName(ThreadTracer.class)+";"));
        newInsns.add(new InsnNode(DUP));
        newInsns.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class),
                "pauseTracing", "()V"));
        newInsns.add(new VarInsnNode(ALOAD, 0));
        newInsns.add(new FieldInsnNode(GETSTATIC,
                Type.getInternalName(ObjectIdentifier.class), "instance",
                "L" + Type.getInternalName(ObjectIdentifier.class) + ";"));
        // TODO this may give different ids to the same object!!
        newInsns.add(new InsnNode(ACONST_NULL));
        newInsns.add(new MethodInsnNode(INVOKEVIRTUAL,
                Type.getInternalName(ObjectIdentifier.class), "getNewId",
                "(Ljava/lang/Object;)J"));
        newInsns.add(new FieldInsnNode(PUTFIELD, classNode.name, ID_FIELD_NAME, "J"));
        newInsns.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class),
                "resumeTracing", "()V"));
        method.instructions.insert(newInsns);
    }
    }
    */
}

From source file:de.unisb.cs.st.javaslicer.tracer.instrumentation.PauseTracingInstrumenter.java

License:Open Source License

@SuppressWarnings("unchecked")
public void transformMethod(final MethodNode method, final ListIterator<MethodNode> methodIt,
        final String className) {
    if ((method.access & ACC_ABSTRACT) != 0 || (method.access & ACC_NATIVE) != 0)
        return;/*w  w w .  j av a2 s  .  c o  m*/

    int tracerLocalVarIndex = (method.access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
    for (final Type t : Type.getArgumentTypes(method.desc))
        tracerLocalVarIndex += t.getSize();

    // increment number of local variables by one (for the threadtracer)
    ++method.maxLocals;

    // and increment all local variable indexes after the new one by one
    for (final Object o : method.localVariables) {
        final LocalVariableNode localVar = (LocalVariableNode) o;
        if (localVar.index >= tracerLocalVarIndex)
            ++localVar.index;
    }
    final LabelNode l0 = new LabelNode();
    final LabelNode l1 = new LabelNode();

    final ListIterator<AbstractInsnNode> insnIt = method.instructions.iterator();

    insnIt.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(Tracer.class), "getInstance",
            "()L" + Type.getInternalName(Tracer.class) + ";", false));
    insnIt.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(Tracer.class), "getThreadTracer",
            "()L" + Type.getInternalName(ThreadTracer.class) + ";", false));
    insnIt.add(new InsnNode(DUP));
    insnIt.add(new VarInsnNode(ASTORE, tracerLocalVarIndex));
    insnIt.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class), "pauseTracing",
            "()V", true));
    insnIt.add(l0);

    while (insnIt.hasNext()) {
        final AbstractInsnNode insn = insnIt.next();
        switch (insn.getType()) {
        case AbstractInsnNode.INSN:
            switch (insn.getOpcode()) {
            case IRETURN:
            case LRETURN:
            case FRETURN:
            case DRETURN:
            case ARETURN:
            case RETURN:
                insnIt.previous();
                insnIt.add(new VarInsnNode(ALOAD, tracerLocalVarIndex));
                insnIt.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class),
                        "resumeTracing", "()V", true));
                insnIt.next();
            }
            break;
        case AbstractInsnNode.IINC_INSN:
            if (((IincInsnNode) insn).var >= tracerLocalVarIndex)
                ++((IincInsnNode) insn).var;
            break;
        case AbstractInsnNode.VAR_INSN:
            if (((VarInsnNode) insn).var >= tracerLocalVarIndex)
                ++((VarInsnNode) insn).var;
            break;
        default:
            break;
        }
    }

    method.instructions.add(l1);

    method.instructions.add(new VarInsnNode(ALOAD, tracerLocalVarIndex));
    method.instructions.add(new MethodInsnNode(INVOKEINTERFACE, Type.getInternalName(ThreadTracer.class),
            "resumeTracing", "()V", true));
    method.instructions.add(new InsnNode(ATHROW));

    method.tryCatchBlocks.add(new TryCatchBlockNode(l0, l1, l1, null));

    // finally: create a copy of the method that gets the ThreadTracer as argument
    if (!"<clinit>".equals(method.name) && this.tracer.wasRedefined(className)) {
        final Type[] oldMethodArguments = Type.getArgumentTypes(method.desc);
        final Type[] newMethodArguments = Arrays.copyOf(oldMethodArguments, oldMethodArguments.length + 1);
        newMethodArguments[oldMethodArguments.length] = Type.getType(ThreadTracer.class);
        final String newMethodDesc = Type.getMethodDescriptor(Type.getReturnType(method.desc),
                newMethodArguments);
        final MethodNode newMethod = new MethodNode(method.access, method.name, newMethodDesc, method.signature,
                (String[]) method.exceptions.toArray(new String[method.exceptions.size()]));
        methodIt.add(newMethod);

        final Map<LabelNode, LabelNode> newMethodLabels = new LazyLabelMap();

        // copy the local variables information to the new method
        for (final Object o : method.localVariables) {
            final LocalVariableNode lv = (LocalVariableNode) o;
            newMethod.localVariables.add(new LocalVariableNode(lv.name, lv.desc, lv.signature,
                    newMethodLabels.get(lv.start), newMethodLabels.get(lv.end), lv.index));
        }

        newMethod.maxLocals = method.maxLocals;
        newMethod.maxStack = method.maxStack;

        // copy the try-catch-blocks
        for (final Object o : method.tryCatchBlocks) {
            final TryCatchBlockNode tcb = (TryCatchBlockNode) o;
            newMethod.tryCatchBlocks.add(new TryCatchBlockNode(newMethodLabels.get(tcb.start),
                    newMethodLabels.get(tcb.end), newMethodLabels.get(tcb.handler), tcb.type));
        }

        // skip the first 4 instructions, replace them with this:
        newMethod.instructions.add(new VarInsnNode(ALOAD, tracerLocalVarIndex));
        final Iterator<AbstractInsnNode> oldInsnIt = method.instructions.iterator(4);
        // and add all the other instructions
        while (oldInsnIt.hasNext()) {
            final AbstractInsnNode insn = oldInsnIt.next();
            newMethod.instructions.add(insn.clone(newMethodLabels));
        }
    }
}

From source file:de.unisb.cs.st.javaslicer.tracer.instrumentation.TracingClassInstrumenter.java

License:Open Source License

@SuppressWarnings("unchecked")
private static void copyMethod(final MethodNode from, final MethodNode to) {
    to.access = from.access;// w w  w .  j av  a 2s .c o m
    to.annotationDefault = from.annotationDefault;
    to.attrs = from.attrs == null ? null : new ArrayList<Attribute>(from.attrs);
    to.desc = from.desc;
    to.exceptions = from.exceptions == null ? null : new ArrayList<String>(from.exceptions);
    to.instructions.clear();
    final Iterator<?> insnIt = from.instructions.iterator();
    final Map<LabelNode, LabelNode> labelsMap = new HashMap<LabelNode, LabelNode>() {
        private static final long serialVersionUID = 6883684625241587713L;

        @Override
        public LabelNode get(final Object key) {
            LabelNode label = super.get(key);
            if (label == null)
                put((LabelNode) key, label = new LabelNode());
            return label;
        }
    };
    while (insnIt.hasNext()) {
        final AbstractInsnNode insn = (AbstractInsnNode) insnIt.next();
        to.instructions.add(insn.clone(labelsMap));
    }
    to.invisibleAnnotations = from.invisibleAnnotations == null ? null
            : new ArrayList<AnnotationNode>(from.invisibleAnnotations);
    if (from.invisibleParameterAnnotations == null) {
        to.invisibleParameterAnnotations = null;
    } else {
        to.invisibleParameterAnnotations = new List[from.invisibleParameterAnnotations.length];
        for (int i = 0; i < from.invisibleParameterAnnotations.length; ++i) {
            to.invisibleParameterAnnotations[i] = from.invisibleParameterAnnotations[i] == null ? null
                    : new ArrayList<AnnotationNode>(from.invisibleParameterAnnotations[i]);
        }
    }
    if (from.localVariables == null) {
        to.localVariables = null;
    } else {
        to.localVariables = new ArrayList<LocalVariableNode>(from.localVariables.size());
        for (final Object lvObj : from.localVariables) {
            final LocalVariableNode lv = (LocalVariableNode) lvObj;
            to.localVariables.add(new LocalVariableNode(lv.name, lv.desc, lv.signature, labelsMap.get(lv.start),
                    labelsMap.get(lv.end), lv.index));
        }
    }
    to.maxLocals = from.maxLocals;
    to.maxStack = from.maxStack;
    to.name = from.name;
    to.signature = from.signature;
    if (from.tryCatchBlocks == null) {
        to.tryCatchBlocks = null;
    } else {
        to.tryCatchBlocks = new ArrayList<TryCatchBlockNode>(from.tryCatchBlocks.size());
        for (final Object tcbObj : from.tryCatchBlocks) {
            final TryCatchBlockNode tcb = (TryCatchBlockNode) tcbObj;
            to.tryCatchBlocks.add(new TryCatchBlockNode(labelsMap.get(tcb.start), labelsMap.get(tcb.end),
                    labelsMap.get(tcb.handler), tcb.type));
        }
    }
    to.visibleAnnotations = from.visibleAnnotations == null ? null
            : new ArrayList<AnnotationNode>(from.visibleAnnotations);
    if (from.visibleParameterAnnotations == null) {
        to.visibleParameterAnnotations = null;
    } else {
        to.visibleParameterAnnotations = new List[from.visibleParameterAnnotations.length];
        for (int i = 0; i < from.visibleParameterAnnotations.length; ++i) {
            to.visibleParameterAnnotations[i] = from.visibleParameterAnnotations[i] == null ? null
                    : new ArrayList<AnnotationNode>(from.visibleParameterAnnotations[i]);
        }
    }
}