/** This routine is not thread-safe */
  private MagicAccessorImpl generate(
      final Class declaringClass,
      String name,
      Class[] parameterTypes,
      Class returnType,
      Class[] checkedExceptions,
      int modifiers,
      boolean isConstructor,
      boolean forSerialization,
      Class serializationTargetClass) {
    ByteVector vec = ByteVectorFactory.create();
    asm = new ClassFileAssembler(vec);
    this.declaringClass = declaringClass;
    this.parameterTypes = parameterTypes;
    this.returnType = returnType;
    this.modifiers = modifiers;
    this.isConstructor = isConstructor;
    this.forSerialization = forSerialization;

    asm.emitMagicAndVersion();

    // Constant pool entries:
    // ( * = Boxing information: optional)
    // (+  = Shared entries provided by AccessorGenerator)
    // (^  = Only present if generating SerializationConstructorAccessor)
    //     [UTF-8] [This class's name]
    //     [CONSTANT_Class_info] for above
    //     [UTF-8]
    // "sun/reflect/{MethodAccessorImpl,ConstructorAccessorImpl,SerializationConstructorAccessorImpl}"
    //     [CONSTANT_Class_info] for above
    //     [UTF-8] [Target class's name]
    //     [CONSTANT_Class_info] for above
    // ^   [UTF-8] [Serialization: Class's name in which to invoke constructor]
    // ^   [CONSTANT_Class_info] for above
    //     [UTF-8] target method or constructor name
    //     [UTF-8] target method or constructor signature
    //     [CONSTANT_NameAndType_info] for above
    //     [CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info] for target method
    //     [UTF-8] "invoke" or "newInstance"
    //     [UTF-8] invoke or newInstance descriptor
    //     [UTF-8] descriptor for type of non-primitive parameter 1
    //     [CONSTANT_Class_info] for type of non-primitive parameter 1
    //     ...
    //     [UTF-8] descriptor for type of non-primitive parameter n
    //     [CONSTANT_Class_info] for type of non-primitive parameter n
    // +   [UTF-8] "java/lang/Exception"
    // +   [CONSTANT_Class_info] for above
    // +   [UTF-8] "java/lang/ClassCastException"
    // +   [CONSTANT_Class_info] for above
    // +   [UTF-8] "java/lang/NullPointerException"
    // +   [CONSTANT_Class_info] for above
    // +   [UTF-8] "java/lang/IllegalArgumentException"
    // +   [CONSTANT_Class_info] for above
    // +   [UTF-8] "java/lang/InvocationTargetException"
    // +   [CONSTANT_Class_info] for above
    // +   [UTF-8] "<init>"
    // +   [UTF-8] "()V"
    // +   [CONSTANT_NameAndType_info] for above
    // +   [CONSTANT_Methodref_info] for NullPointerException's constructor
    // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor
    // +   [UTF-8] "(Ljava/lang/String;)V"
    // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V"
    // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String
    // +   [UTF-8] "(Ljava/lang/Throwable;)V"
    // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V"
    // +   [CONSTANT_Methodref_info] for InvocationTargetException's constructor
    // +   [CONSTANT_Methodref_info] for "super()"
    // +   [UTF-8] "java/lang/Object"
    // +   [CONSTANT_Class_info] for above
    // +   [UTF-8] "toString"
    // +   [UTF-8] "()Ljava/lang/String;"
    // +   [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;"
    // +   [CONSTANT_Methodref_info] for Object's toString method
    // +   [UTF-8] "Code"
    // +   [UTF-8] "Exceptions"
    //  *  [UTF-8] "java/lang/Boolean"
    //  *  [CONSTANT_Class_info] for above
    //  *  [UTF-8] "(Z)V"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "booleanValue"
    //  *  [UTF-8] "()Z"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "java/lang/Byte"
    //  *  [CONSTANT_Class_info] for above
    //  *  [UTF-8] "(B)V"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "byteValue"
    //  *  [UTF-8] "()B"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "java/lang/Character"
    //  *  [CONSTANT_Class_info] for above
    //  *  [UTF-8] "(C)V"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "charValue"
    //  *  [UTF-8] "()C"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "java/lang/Double"
    //  *  [CONSTANT_Class_info] for above
    //  *  [UTF-8] "(D)V"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "doubleValue"
    //  *  [UTF-8] "()D"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "java/lang/Float"
    //  *  [CONSTANT_Class_info] for above
    //  *  [UTF-8] "(F)V"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "floatValue"
    //  *  [UTF-8] "()F"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "java/lang/Integer"
    //  *  [CONSTANT_Class_info] for above
    //  *  [UTF-8] "(I)V"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "intValue"
    //  *  [UTF-8] "()I"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "java/lang/Long"
    //  *  [CONSTANT_Class_info] for above
    //  *  [UTF-8] "(J)V"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "longValue"
    //  *  [UTF-8] "()J"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "java/lang/Short"
    //  *  [CONSTANT_Class_info] for above
    //  *  [UTF-8] "(S)V"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above
    //  *  [UTF-8] "shortValue"
    //  *  [UTF-8] "()S"
    //  *  [CONSTANT_NameAndType_info] for above
    //  *  [CONSTANT_Methodref_info] for above

    short numCPEntries = NUM_BASE_CPOOL_ENTRIES + NUM_COMMON_CPOOL_ENTRIES;
    boolean usesPrimitives = usesPrimitiveTypes();
    if (usesPrimitives) {
      numCPEntries += NUM_BOXING_CPOOL_ENTRIES;
    }
    if (forSerialization) {
      numCPEntries += NUM_SERIALIZATION_CPOOL_ENTRIES;
    }

    // Add in variable-length number of entries to be able to describe
    // non-primitive parameter types and checked exceptions.
    numCPEntries += (short) (2 * numNonPrimitiveParameterTypes());

    asm.emitShort(add(numCPEntries, S1));

    final String generatedName = generateName(isConstructor, forSerialization);
    asm.emitConstantPoolUTF8(generatedName);
    asm.emitConstantPoolClass(asm.cpi());
    thisClass = asm.cpi();
    if (isConstructor) {
      if (forSerialization) {
        asm.emitConstantPoolUTF8("sun/reflect/SerializationConstructorAccessorImpl");
      } else {
        asm.emitConstantPoolUTF8("sun/reflect/ConstructorAccessorImpl");
      }
    } else {
      asm.emitConstantPoolUTF8("sun/reflect/MethodAccessorImpl");
    }
    asm.emitConstantPoolClass(asm.cpi());
    superClass = asm.cpi();
    asm.emitConstantPoolUTF8(getClassName(declaringClass, false));
    asm.emitConstantPoolClass(asm.cpi());
    targetClass = asm.cpi();
    short serializationTargetClassIdx = (short) 0;
    if (forSerialization) {
      asm.emitConstantPoolUTF8(getClassName(serializationTargetClass, false));
      asm.emitConstantPoolClass(asm.cpi());
      serializationTargetClassIdx = asm.cpi();
    }
    asm.emitConstantPoolUTF8(name);
    asm.emitConstantPoolUTF8(buildInternalSignature());
    asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
    if (isInterface()) {
      asm.emitConstantPoolInterfaceMethodref(targetClass, asm.cpi());
    } else {
      if (forSerialization) {
        asm.emitConstantPoolMethodref(serializationTargetClassIdx, asm.cpi());
      } else {
        asm.emitConstantPoolMethodref(targetClass, asm.cpi());
      }
    }
    targetMethodRef = asm.cpi();
    if (isConstructor) {
      asm.emitConstantPoolUTF8("newInstance");
    } else {
      asm.emitConstantPoolUTF8("invoke");
    }
    invokeIdx = asm.cpi();
    if (isConstructor) {
      asm.emitConstantPoolUTF8("([Ljava/lang/Object;)Ljava/lang/Object;");
    } else {
      asm.emitConstantPoolUTF8("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
    }
    invokeDescriptorIdx = asm.cpi();

    // Output class information for non-primitive parameter types
    nonPrimitiveParametersBaseIdx = add(asm.cpi(), S2);
    for (int i = 0; i < parameterTypes.length; i++) {
      Class c = parameterTypes[i];
      if (!isPrimitive(c)) {
        asm.emitConstantPoolUTF8(getClassName(c, false));
        asm.emitConstantPoolClass(asm.cpi());
      }
    }

    // Entries common to FieldAccessor, MethodAccessor and ConstructorAccessor
    emitCommonConstantPoolEntries();

    // Boxing entries
    if (usesPrimitives) {
      emitBoxingContantPoolEntries();
    }

    if (asm.cpi() != numCPEntries) {
      throw new InternalError(
          "Adjust this code (cpi = " + asm.cpi() + ", numCPEntries = " + numCPEntries + ")");
    }

    // Access flags
    asm.emitShort(ACC_PUBLIC);

    // This class
    asm.emitShort(thisClass);

    // Superclass
    asm.emitShort(superClass);

    // Interfaces count and interfaces
    asm.emitShort(S0);

    // Fields count and fields
    asm.emitShort(S0);

    // Methods count and methods
    asm.emitShort(NUM_METHODS);

    emitConstructor();
    emitInvoke();

    // Additional attributes (none)
    asm.emitShort(S0);

    // Load class
    vec.trim();
    final byte[] bytes = vec.getData();
    // Note: the class loader is the only thing that really matters
    // here -- it's important to get the generated code into the
    // same namespace as the target class. Since the generated code
    // is privileged anyway, the protection domain probably doesn't
    // matter.
    return (MagicAccessorImpl)
        AccessController.doPrivileged(
            new PrivilegedAction() {
              public Object run() {
                try {
                  return ClassDefiner.defineClass(
                          generatedName, bytes, 0, bytes.length, declaringClass.getClassLoader())
                      .newInstance();
                } catch (InstantiationException e) {
                  throw (InternalError) new InternalError().initCause(e);
                } catch (IllegalAccessException e) {
                  throw (InternalError) new InternalError().initCause(e);
                }
              }
            });
  }