Handle getLambdaAccessMethod(Handle implMethod) {
   if (!implMethod.getOwner().equals(className)) {
     return implMethod;
   }
   if (Flags.hasFlag(classAccess, ACC_INTERFACE)) {
     // the method will be relocated to a companion class
     return implMethod;
   }
   // TODO: do not generate an access method if the impl method is not private (probably not
   // implementable with a single pass)
   String name = "access$lambda$" + lambdaAccessToImplMethods.size();
   String desc = getLambdaAccessMethodDesc(implMethod);
   Handle accessMethod = new Handle(H_INVOKESTATIC, className, name, desc);
   lambdaAccessToImplMethods.put(accessMethod, implMethod);
   return accessMethod;
 }
 @Override
 public MethodVisitor visitMethod(
     final int access,
     final String name,
     final String desc,
     final String signature,
     final String[] exceptions) {
   Object key = Arrays.asList(name, desc);
   if (visitedMethods.contains(key)) return EMPTY_VISITOR;
   if (Modifier.isPrivate(access)
       || Modifier.isNative(access)
       || ((access & ACC_SYNTHETIC) != 0)) {
     // do not generate bytecode for private methods
     return EMPTY_VISITOR;
   }
   int accessFlags = access;
   visitedMethods.add(key);
   if ((objectDelegateMethods.contains(name)
           || delegatedClosures.containsKey(name)
           || (!"<init>".equals(name) && hasWildcard))
       && !Modifier.isStatic(access)
       && !Modifier.isFinal(access)) {
     if (!GROOVYOBJECT_METHOD_NAMESS.contains(name)) {
       if (Modifier.isAbstract(access)) {
         // prevents the proxy from being abstract
         accessFlags -= ACC_ABSTRACT;
       }
       if (delegatedClosures.containsKey(name) || (!"<init>".equals(name) && hasWildcard)) {
         delegatedClosures.put(name, Boolean.TRUE);
         return makeDelegateToClosureCall(name, desc, signature, exceptions, accessFlags);
       }
       if (generateDelegateField && objectDelegateMethods.contains(name)) {
         return makeDelegateCall(name, desc, signature, exceptions, accessFlags);
       }
       delegatedClosures.put(name, Boolean.TRUE);
       return makeDelegateToClosureCall(name, desc, signature, exceptions, accessFlags);
     }
   } else if ("<init>".equals(name)
       && (Modifier.isPublic(access) || Modifier.isProtected(access))) {
     return createConstructor(access, name, desc, signature, exceptions);
   } else if (Modifier.isAbstract(access) && !GROOVYOBJECT_METHOD_NAMESS.contains(name)) {
     accessFlags -= ACC_ABSTRACT;
     MethodVisitor mv = super.visitMethod(accessFlags, name, desc, signature, exceptions);
     mv.visitCode();
     Type[] args = Type.getArgumentTypes(desc);
     if (emptyBody) {
       Type returnType = Type.getReturnType(desc);
       if (returnType == Type.VOID_TYPE) {
         mv.visitInsn(RETURN);
       } else {
         int loadIns = getLoadInsn(returnType);
         switch (loadIns) {
           case ILOAD:
             mv.visitInsn(ICONST_0);
             break;
           case LLOAD:
             mv.visitInsn(LCONST_0);
             break;
           case FLOAD:
             mv.visitInsn(FCONST_0);
             break;
           case DLOAD:
             mv.visitInsn(DCONST_0);
             break;
           default:
             mv.visitInsn(ACONST_NULL);
         }
         mv.visitInsn(getReturnInsn(returnType));
         mv.visitMaxs(2, registerLen(args) + 1);
       }
     } else {
       // for compatibility with the legacy proxy generator, we should throw an
       // UnsupportedOperationException
       // instead of an AbtractMethodException
       mv.visitTypeInsn(NEW, "java/lang/UnsupportedOperationException");
       mv.visitInsn(DUP);
       mv.visitMethodInsn(
           INVOKESPECIAL, "java/lang/UnsupportedOperationException", "<init>", "()V");
       mv.visitInsn(ATHROW);
       mv.visitMaxs(2, registerLen(args) + 1);
     }
     mv.visitEnd();
   }
   return EMPTY_VISITOR;
 }