private void doVisitMethodInsn(
     int opcode, final String owner, final String name, final String desc, final boolean itf) {
   checkStartCode();
   checkEndCode();
   checkOpcode(opcode, 5);
   if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) {
     checkMethodIdentifier(version, name, "name");
   }
   checkInternalName(owner, "owner");
   checkMethodDesc(desc);
   if (opcode == Opcodes.INVOKEVIRTUAL && itf) {
     throw new IllegalArgumentException("INVOKEVIRTUAL can't be used with interfaces");
   }
   if (opcode == Opcodes.INVOKEINTERFACE && !itf) {
     throw new IllegalArgumentException("INVOKEINTERFACE can't be used with classes");
   }
   // Calling super.visitMethodInsn requires to call the correct version
   // depending on this.api (otherwise infinite loops can occur). To
   // simplify and to make it easier to automatically remove the backward
   // compatibility code, we inline the code of the overridden method here.
   if (mv != null) {
     mv.visitMethodInsn(opcode, owner, name, desc, itf);
   }
   ++insnCount;
 }
 @Override
 public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
   checkStartCode();
   checkEndCode();
   checkMethodIdentifier(version, name, "name");
   checkMethodDesc(desc);
   if (bsm.getTag() != Opcodes.H_INVOKESTATIC && bsm.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
     throw new IllegalArgumentException("invalid handle tag " + bsm.getTag());
   }
   for (int i = 0; i < bsmArgs.length; i++) {
     checkLDCConstant(bsmArgs[i]);
   }
   super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
   ++insnCount;
 }