docs: private static void addEJBAsynchMethod(ClassWriter cw,
                                             String className,
                                             Method method,
                                             int methodId,
                                             boolean isRmiRemote,
                                             EJBWrapperType wrapperType)
      {
          GeneratorAdapter mg;
          String methodName = method.getName();
          String methodSignature = MethodAttribUtils.jdiMethodSignature(method);
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
              Tr.debug(tc, INDENT + "adding asynch method : " + methodName + " "
                           + methodSignature);
  
          // Determine the list of 'checked' exceptions, which will need to have
          // catch blocks in the wrapper... and also perform validation.
          // Note that RemoteException is never a 'checked' exception, and
          // exceptions that are subclasses of other 'checked' exceptions
          // will be eliminated, to avoid 'unreachable' code.
          Class<?>[] methodExceptions = method.getExceptionTypes();
  
          // Convert the return value, arguments, and exception classes to
          // ASM Type objects, and create the ASMMethod object which will
          // be used to actually add the method and method code.
          Type returnType = Type.getType(method.getReturnType());
          Type[] argTypes = getTypes(method.getParameterTypes());
          Type[] exceptionTypes = getTypes(methodExceptions);
  
          org.objectweb.asm.commons.Method m = new org.objectweb.asm.commons.Method(
                          methodName, returnType, argTypes);
  
          // Create an ASM GeneratorAdapter object for the ASM Method, which
          // makes generating dynamic code much easier... as it keeps track
          // of the position of the arguments and local variables, etc.
          mg = new GeneratorAdapter(ACC_PUBLIC, m, null, exceptionTypes, cw);
  
          // -----------------------------------------------------------------------
          // Begin Method Code...
          // -----------------------------------------------------------------------
          mg.visitCode();
  
          // -----------------------------------------------------------------------
          // EJSDeployedSupport s = new EJSDeployedSupport();
          // -----------------------------------------------------------------------
          int s = mg.newLocal(TYPE_EJSDeployedSupport);
          mg.newInstance(TYPE_EJSDeployedSupport);
          mg.dup();
          mg.visitMethodInsn(INVOKESPECIAL, "com/ibm/ejs/container/EJSDeployedSupport", "<init>", "()V");
          mg.storeLocal(s);
  
          // -----------------------------------------------------------------------
          // returnValue = null
          // -----------------------------------------------------------------------
          int returnValue = -1;
          if (returnType != Type.VOID_TYPE) // F743-609CodRev
                                            // If method return type is not void, save room on stack for return value.
          {
              returnValue = mg.newLocal(returnType);
  
              // push a null on the stack
              mg.visitInsn(ACONST_NULL);
  
              mg.storeLocal(returnValue);
          }
  
          // --------------------------------------------------------------------
          // Object[] args = null;
          // --------------------------------------------------------------------
          int args = mg.newLocal(TYPE_Object_ARRAY);
          mg.visitInsn(ACONST_NULL);
          mg.storeLocal(args);
  
          // -----------------------------------------------------------------------
          // args = new Object[# of args];
          // -----------------------------------------------------------------------
          mg.push(argTypes.length);
          mg.visitTypeInsn(ANEWARRAY, "java/lang/Object");
          mg.storeLocal(args);
  
          // -----------------------------------------------------------------------
          // args[i] = "parameter"; -> for each parameter
          // -----------------------------------------------------------------------
          for (int i = 0; i < argTypes.length; i++) {
              mg.loadLocal(args);
              mg.push(i);
  
              // Convert primitives to objects to put in 'args' array.
              switch (argTypes[i].getSort()) {
                  case Type.BOOLEAN:
                      mg.visitTypeInsn(NEW, "java/lang/Boolean");
                      mg.visitInsn(DUP);
                      mg.loadArg(i); // for non-static, arg 0 = "this"
                      mg.visitMethodInsn(INVOKESPECIAL, "java/lang/Boolean", "<init>",
                                         "(Z)V");
                      break;
  
                  case Type.CHAR:
                      mg.visitTypeInsn(NEW, "java/lang/Character");
                      mg.visitInsn(DUP);
                      mg.loadArg(i); // for non-static, arg 0 = "this"
                      mg.visitMethodInsn(INVOKESPECIAL, "java/lang/Character", "<init>",
                                         "(C)V");
                      break;
  
                  case Type.BYTE:
                      mg.visitTypeInsn(NEW, "java/lang/Byte");
                      mg.visitInsn(DUP);
                      mg.loadArg(i); // for non-static, arg 0 = "this"
                      mg.visitMethodInsn(INVOKESPECIAL, "java/lang/Byte", "<init>",
                                         "(B)V");
                      break;
  
                  case Type.SHORT:
                      mg.visitTypeInsn(NEW, "java/lang/Short");
                      mg.visitInsn(DUP);
                      mg.loadArg(i); // for non-static, arg 0 = "this"
                      mg.visitMethodInsn(INVOKESPECIAL, "java/lang/Short", "<init>",
                                         "(S)V");
                      break;
  
                  case Type.INT:
                      mg.visitTypeInsn(NEW, "java/lang/Integer");
                      mg.visitInsn(DUP);
                      mg.loadArg(i); // for non-static, arg 0 = "this"
                      mg.visitMethodInsn(INVOKESPECIAL, "java/lang/Integer", "<init>",
                                         "(I)V");
                      break;
  
                  case Type.FLOAT:
                      mg.visitTypeInsn(NEW, "java/lang/Float");
                      mg.visitInsn(DUP);
                      mg.loadArg(i); // for non-static, arg 0 = "this"
                      mg.visitMethodInsn(INVOKESPECIAL, "java/lang/Float", "<init>",
                                         "(F)V");
                      break;
  
                  case Type.LONG:
                      mg.visitTypeInsn(NEW, "java/lang/Long");
                      mg.visitInsn(DUP);
                      mg.loadArg(i); // for non-static, arg 0 = "this"
                      mg.visitMethodInsn(INVOKESPECIAL, "java/lang/Long", "<init>",
                                         "(J)V");
                      break;
  
                  case Type.DOUBLE:
                      mg.visitTypeInsn(NEW, "java/lang/Double");
                      mg.visitInsn(DUP);
                      mg.loadArg(i); // for non-static, arg 0 = "this"
                      mg.visitMethodInsn(INVOKESPECIAL, "java/lang/Double", "<init>",
                                         "(D)V");
                      break;
  
                  // ARRAY & OBJECT - no need to copy, just load the arg
                  default:
                      mg.loadArg(i); // for non-static, arg 0 = "this"
                      break;
              }
  
              mg.visitInsn(AASTORE);
  
          } // End for loop
  
          // -----------------------------------------------------------------------
          // returnValue = container.scheduleAsynchMethod( this,
          //                                               methodId,
          //                                               args);
          // -----------------------------------------------------------------------
          loadContainer(mg, className, wrapperType);
          loadWrapperBase(mg, className, wrapperType); // F743-1756
          mg.push(methodId);
          mg.loadLocal(args);
          mg.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/ejs/container/EJSContainer",
                             "scheduleAsynchMethod",
                             "(Lcom/ibm/ejs/container/EJSWrapperBase;I[Ljava/lang/Object;)Ljava/util/concurrent/Future;");
  
          // F743-609CodRev
          // If method return type is not void, store the return value on the stack.
          // Otherwise, pop the extra space off the stack.  We don't have anything to return.
          if (returnType != Type.VOID_TYPE) {
              mg.storeLocal(returnValue);
          } else {
              mg.pop();
          }
  
          // -----------------------------------------------------------------------
          // return
          // -----------------------------------------------------------------------
          if (returnType != Type.VOID_TYPE) {
              mg.loadLocal(returnValue);
          }
          mg.returnValue();
  
          // -----------------------------------------------------------------------
          // End Asynch Method Code...
          // -----------------------------------------------------------------------
          mg.endMethod(); // GeneratorAdapter accounts for visitMaxs(x,y)
          mg.visitEnd();
      }