docs: private static void addManagedBeanMethod(ClassWriter cw,
                                               String className,
                                               String implClassName,
                                               Method method,
                                               String implMethodName,
                                               int methodId,
                                               boolean aroundInvoke)
      {
          GeneratorAdapter mg;
          String methodName = method.getName();
          String methodSignature = MethodAttribUtils.jdiMethodSignature(method);
          String EjbPreInvoke = "EjbPreInvokeForManagedBean";
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
              Tr.debug(tc, INDENT + "adding method : " +
                           methodName + " " + methodSignature +
                           " : aroundInvoke = " + aroundInvoke);
  
          // 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 ASM Method 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();
  
          // -----------------------------------------------------------------------
          // When no AroundInvoke interceptors... the code is very simple - the
          // method call is just passed through to the actual instance, which may
          // be found in the BeanO stored on the wrapper.
          // -----------------------------------------------------------------------
          if (!aroundInvoke)
          {
              // --------------------------------------------------------------------
              //   <bean impl> bean = (<bean impl>)ivBeanO.getBeanInstance();
              // --------------------------------------------------------------------
              Type implType = Type.getType("L" + implClassName + ";");
              int bean = mg.newLocal(implType);
              mg.loadThis();
              mg.visitFieldInsn(GETFIELD, className, "ivBeanO",
                                "Lcom/ibm/ejs/container/BeanO;");
              mg.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/ejs/container/BeanO",
                                 "getBeanInstance", "()Ljava/lang/Object;");
              mg.checkCast(implType);
              mg.storeLocal(bean);
  
              // --------------------------------------------------------------------
              //   bean.<method>(<args...>);
              //      or
              //   rtnValue = bean.<method>(<args...>);
              // --------------------------------------------------------------------
              mg.loadLocal(bean);
              mg.loadArgs(0, argTypes.length); // do not pass "this"
              mg.visitMethodInsn(INVOKEVIRTUAL, implClassName, implMethodName,
                                 m.getDescriptor());
              mg.returnValue();
  
              // -----------------------------------------------------------------------
              // End Method Code...
              // -----------------------------------------------------------------------
              mg.endMethod(); // GeneratorAdapter accounts for visitMaxs(x,y)
              mg.visitEnd();
  
              return;
          }
  
          // -----------------------------------------------------------------------
          // The rest of the code is for handling AroundInvoke interceptors.
          // -----------------------------------------------------------------------
  
          // -----------------------------------------------------------------------
          // 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);
  
          // -----------------------------------------------------------------------
          // <return type> returnValue = false | 0 | null;
          // -----------------------------------------------------------------------
          int returnValue = -1;
          if (returnType != Type.VOID_TYPE)
          {
              returnValue = mg.newLocal(returnType);
              switch (returnType.getSort())
              {
                  case Type.BOOLEAN:
                      mg.push(false);
                      break;
  
                  case Type.CHAR:
                  case Type.BYTE:
                  case Type.SHORT:
                  case Type.INT:
                      mg.push(0);
                      break;
  
                  case Type.FLOAT:
                      mg.push((float) 0);
                      break;
  
                  case Type.LONG:
                      mg.push((long) 0);
                      break;
  
                  case Type.DOUBLE:
                      mg.push((double) 0);
                      break;
  
                  // ARRAY & OBJECT - push a null on the stack
                  default:
                      mg.visitInsn(ACONST_NULL);
                      break;
              }
              mg.storeLocal(returnValue);
          }
  
          // -----------------------------------------------------------------------
          // Object[] args;
          // -----------------------------------------------------------------------
          int args = mg.newLocal(TYPE_Object_ARRAY);
  
          // -----------------------------------------------------------------------
          // 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);
          }
  
          // -----------------------------------------------------------------------
          // <bean impl> bean = (bean impl)container.EjbPreInvokeForManagedBean
          //                                                    ( this,
          //                                                      methodId,
          //                                                      s,
          //                                                      ivBeanO,
          //                                                      args );
          // -----------------------------------------------------------------------
          Type implType = Type.getType("L" + implClassName + ";");
          int bean = mg.newLocal(implType);
          loadContainer(mg, className, MANAGED_BEAN);
          loadWrapperBase(mg, className, MANAGED_BEAN);
          mg.push(methodId);
          mg.loadLocal(s);
          mg.loadThis();
          mg.visitFieldInsn(GETFIELD, className, "ivBeanO", "Lcom/ibm/ejs/container/BeanO;");
          mg.loadLocal(args);
          mg.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/ejs/container/EJSContainer",
                             EjbPreInvoke,
                             "(Lcom/ibm/ejs/container/EJSWrapperBase;ILcom/ibm/ejs/container/EJSDeployedSupport;Lcom/ibm/ejs/container/BeanO;[Ljava/lang/Object;)Ljava/lang/Object;");
          mg.checkCast(implType);
          mg.storeLocal(bean);
  
          // -----------------------------------------------------------------------
          // Now invoke the business method through the interceptors via
          // EJSContainer.invoke();
          // -----------------------------------------------------------------------
  
          // --------------------------------------------------------------------
          // container.invoke(s);
          //    or
          // rtnValue = (type)container.invoke(s);
          //    or
          // rtnValue = ((object type)container.invoke(s)).<type>Value();  // unbox
          // --------------------------------------------------------------------
          loadContainer(mg, className, MANAGED_BEAN);
          mg.loadLocal(s);
          mg.visitInsn(ACONST_NULL);
          mg.visitMethodInsn(INVOKEVIRTUAL, "com/ibm/ejs/container/EJSContainer",
                             "invoke",
                             "(Lcom/ibm/ejs/container/EJSDeployedSupport;Ljavax/ejb/Timer;)Ljava/lang/Object;");
  
          if (returnType == Type.VOID_TYPE)
          {
              // No return value, just pop the returned value (null) off the stack
              mg.pop();
          }
          else
          {
              // Unbox any primitive values or add the appropriate cast
              // for object/array values, and then store in local variable. d369262.7
              unbox(mg, returnType);
              mg.storeLocal(returnValue);
          }
  
          // -----------------------------------------------------------------------
          // return
          // -----------------------------------------------------------------------
          if (returnType != Type.VOID_TYPE)
          {
              mg.loadLocal(returnValue);
          }
          mg.returnValue();
  
          // -----------------------------------------------------------------------
          // End Method Code...
          // -----------------------------------------------------------------------
          mg.endMethod(); // GeneratorAdapter accounts for visitMaxs(x,y)
          mg.visitEnd();
      }