icegem-core/src/main/java/com/googlecode/icegem/serialization/codegen/DataSerializerGenerator.java
public static synchronized List<Class<?>> generateDataSerializerClasses(ClassLoader classLoader,
            List<Class<?>> classList, String outputDir) throws CannotCompileException, InvalidClassException {
        checkClassesValid(classList);

        List<CtClass> dataSerializerClassList = new ArrayList<CtClass>();

        // create new ClassPool for every method call
        // 1) low memory consumption - any caches with internal data structures of created classes
        // 2) any collision between methods called serially - all crated classes are forgotten
        // 3) any references on created classes from this lib
        ClassPool classPool = newClassPool(classLoader);

        // #1: create dataSerializers with stubs toData/fromData
        for (Class<?> clazz : classList) {
            String serializerClsName = createDataSerializerClassNameForClass(clazz);

            if (existsClass(serializerClsName, classLoader)) {
                logger.debug("Serializer for class {} exists. Skipping generation", clazz.getName());
                break;
            }

            // create class
            CtClass cc = createClass(classPool, clazz, serializerClsName);

            dataSerializerClassList.add(cc);
            
            // add static Register
            addStaticConstruct(clazz, cc, serializerClsName);
            // add methods
            addMethodGetId(clazz, cc);
            addMethodGetSupportedClasses(clazz, cc);
            // add stub-methods toData/fromData
            addMethodToDataStub(clazz, cc);
            addMethodFromDataStub(clazz, cc);
            // we need this for Javassist do some magic with CtClass
            try {
                cc.toBytecode();
            } catch (IOException e) {
                throw new CannotCompileException(
                        "Error during end of compilation phase #1 (call CtClass.toBytecode() for some Javassist-magic with CtClass) for "
                                + cc.getName(), e);
            } catch (CannotCompileException e) {
                throw new CannotCompileException(
                        "Error during end of compilation phase #1 (call CtClass.toBytecode() for some Javassist-magic with CtClass) for "
                                + cc.getName(), e);
            }
        }

        List<Class<?>> result = new ArrayList<Class<?>>();
        // #2: change stubs toData/fromData in dataSerializers -> real methods
        for (int k = 0; k < classList.size(); k++) {
            Class<?> clazz = classList.get(k);
            CtClass cc = dataSerializerClassList.get(k);
            // make changing methods real: defrost CtClass
            cc.defrost();
            // change stub toData/fromData -> real methods
            addMethodToData(clazz, cc);
            addMethodFromData(clazz, cc);
            // generate result
            final Class<?> resultClass;
            try {
                resultClass = cc.toClass(classLoader, null); // ProtectionDomain == null
                logger.info("compiled data serializer for class: {}; id: {}; version: {}",
                        new Object[] { clazz, clazz.getAnnotation(AutoSerializable.class).dataSerializerID()
                                , clazz.getAnnotation(BeanVersion.class).value() });
                if ((outputDir != null) && (outputDir.length() > 0)) {
                    try {
                        cc.writeFile(outputDir);
                    } catch (IOException e) {
                        throw new RuntimeException("couldn't save DataSerializer for class " + clazz.getName(), e);
                    }
                }
            } catch (CannotCompileException e) {
                throw new CannotCompileException(
                        "Error during end of compilation phase #2 (call CtClass.toClass()) for " + cc.getName()
                                + ". Probably you second time try generate and load DataSerializer class "
                                + cc.getName() + " for class " + clazz.getName(), e);
            }

            // dump code to listener
            if (listener != null) {
                listener.generated(clazz.getName(), cc.getName(), new ClassProcessor().process(new XClass(clazz), cc.getName()));
            }

            result.add(resultClass);
        }

        return result;
    }
public static synchronized List<Class<?>> generateDataSerializerClasses(ClassLoader classLoader,
            List<Class<?>> classList, String outputDir) throws CannotCompileException, InvalidClassException {
        checkClassesValid(classList);

        List<CtClass> dataSerializerClassList = new ArrayList<CtClass>();

        // create new ClassPool for every method call
        // 1) low memory consumption - any caches with internal data structures of created classes
        // 2) any collision between methods called serially - all crated classes are forgotten
        // 3) any references on created classes from this lib
        ClassPool classPool = newClassPool(classLoader);

        // #1: create dataSerializers with stubs toData/fromData
        for (Class<?> clazz : classList) {
            String serializerClsName = createDataSerializerClassNameForClass(clazz);

            if (existsClass(serializerClsName, classLoader)) {
                logger.debug("Serializer for class {} exists. Skipping generation", clazz.getName());
                break;
            }

            // create class
            CtClass cc = createClass(classPool, clazz, serializerClsName);

            dataSerializerClassList.add(cc);
            
            // add static Register
            addStaticConstruct(clazz, cc, serializerClsName);
            // add methods
            addMethodGetId(clazz, cc);
            addMethodGetSupportedClasses(clazz, cc);
            // add stub-methods toData/fromData
            addMethodToDataStub(clazz, cc);
            addMethodFromDataStub(clazz, cc);
            // we need this for Javassist do some magic with CtClass
            try {
                cc.toBytecode();
            } catch (IOException e) {
                throw new CannotCompileException(
                        "Error during end of compilation phase #1 (call CtClass.toBytecode() for some Javassist-magic with CtClass) for "
                                + cc.getName(), e);
            } catch (CannotCompileException e) {
                throw new CannotCompileException(
                        "Error during end of compilation phase #1 (call CtClass.toBytecode() for some Javassist-magic with CtClass) for "
                                + cc.getName(), e);
            }
        }

        List<Class<?>> result = new ArrayList<Class<?>>();
        // #2: change stubs toData/fromData in dataSerializers -> real methods
        for (int k = 0; k < classList.size(); k++) {
            Class<?> clazz = classList.get(k);
            CtClass cc = dataSerializerClassList.get(k);
            // make changing methods real: defrost CtClass
            cc.defrost();
            // change stub toData/fromData -> real methods
            addMethodToData(clazz, cc);
            addMethodFromData(clazz, cc);
            // generate result
            final Class<?> resultClass;
            try {
                resultClass = cc.toClass(classLoader, null); // ProtectionDomain == null
                logger.info("compiled data serializer for class: {}; id: {}; version: {}",
                        new Object[] { clazz, clazz.getAnnotation(AutoSerializable.class).dataSerializerID()
                                , clazz.getAnnotation(BeanVersion.class).value() });
                if ((outputDir != null) && (outputDir.length() > 0)) {
                    try {
                        cc.writeFile(outputDir);
                    } catch (IOException e) {
                        throw new RuntimeException("couldn't save DataSerializer for class " + clazz.getName(), e);
                    }
                }
            } catch (CannotCompileException e) {
                throw new CannotCompileException(
                        "Error during end of compilation phase #2 (call CtClass.toClass()) for " + cc.getName()
                                + ". Probably you second time try generate and load DataSerializer class "
                                + cc.getName() + " for class " + clazz.getName(), e);
            }

            // dump code to listener
            if (listener != null) {
                listener.generated(clazz.getName(), cc.getName(), new ClassProcessor().process(new XClass(clazz), cc.getName()));
            }

            result.add(resultClass);
        }

        return result;
    }
2-stage compilation scheme of group of classes: <p> hack from
http://www.csg.is.titech.ac.jp/~chiba/javassist/tutorial/tutorial2.html#add <p> order of return of
serializer-classes in response corresponds to order of arg-classes