diff --git a/java/src/main/java/org/msgpack/util/codegen/Constants.java b/java/src/main/java/org/msgpack/util/codegen/Constants.java
index 8a4b7085..b85c94d9 100644
--- a/java/src/main/java/org/msgpack/util/codegen/Constants.java
+++ b/java/src/main/java/org/msgpack/util/codegen/Constants.java
@@ -21,6 +21,8 @@ public interface Constants {
 
 	String VARIABLE_NAME_TEMPLATES = "_$$_templates";
 
+	String VARIABLE_NAME_PACKERS = "_$$_packers";
+
 	String VARIABLE_NAME_CLIENT = "_$$_client";
 
 	String METHOD_NAME_BOOLEANVALUE = "booleanValue";
@@ -43,6 +45,8 @@ public interface Constants {
 
 	String METHOD_NAME_SETTEMPLATES = "setTemplates";
 
+	String METHOD_NAME_SETMESSAGEPACKERS = "setMessagePackers";
+
 	String METHOD_NAME_PACK = "pack";
 
 	String METHOD_NAME_UNPACK = "unpack";
@@ -103,7 +107,7 @@ public interface Constants {
 
 	String STATEMENT_PACKER_PACKERMETHODBODY_02 = "$1.packArray(%d); ";
 
-	String STATEMENT_PACKER_PACKERMETHODBODY_03 = "$1.pack(_$$_t.%s); ";
+	String STATEMENT_PACKER_PACKERMETHODBODY_03 = "_$$_packers[%d].pack($1, %s_$$_t.%s%s); ";
 
 	String STATEMENT_PACKER_PACKERMETHODBODY_04 = "$1.pack(((java.lang.Enum)_$$_t).ordinal()); ";
 
diff --git a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java
index bb9cdd56..3cf8043a 100644
--- a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java
+++ b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java
@@ -5,7 +5,6 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
-import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -17,19 +16,14 @@ import javassist.CtMethod;
 import javassist.CtNewMethod;
 import javassist.NotFoundException;
 
-import org.msgpack.CustomMessage;
-import org.msgpack.CustomPacker;
 import org.msgpack.MessagePackObject;
-import org.msgpack.MessagePackable;
 import org.msgpack.MessagePacker;
 import org.msgpack.MessageTypeException;
 import org.msgpack.Packer;
 import org.msgpack.Template;
 import org.msgpack.Unpacker;
-import org.msgpack.annotation.MessagePackDelegate;
-import org.msgpack.annotation.MessagePackMessage;
 import org.msgpack.annotation.MessagePackOptional;
-import org.msgpack.annotation.MessagePackOrdinalEnum;
+import org.msgpack.packer.OptionalPacker;
 import org.msgpack.template.OptionalTemplate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -51,9 +45,12 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
 
 	private ConcurrentHashMap<String, Template[]> tmplCache;
 
+	private ConcurrentHashMap<String, MessagePacker[]> pkCache;
+
 	DynamicCodeGen() {
 		super();
 		tmplCache = new ConcurrentHashMap<String, Template[]>();
+		pkCache = new ConcurrentHashMap<String, MessagePacker[]>();
 	}
 
 	public void setTemplates(Class<?> type, Template[] tmpls) {
@@ -64,6 +61,14 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
 		return tmplCache.get(type.getName());
 	}
 
+	public void setMessagePackers(Class<?> type, MessagePacker[] pks) {
+		pkCache.putIfAbsent(type.getName(), pks);
+	}
+
+	public MessagePacker[] getMessagePackers(Class<?> type) {
+		return pkCache.get(type.getName());
+	}
+
 	public Class<?> generateMessagePackerClass(Class<?> origClass,
 			List<FieldOption> fieldOpts) {
 		try {
@@ -74,12 +79,18 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
 			checkTypeValidation(origClass);
 			checkDefaultConstructorValidation(origClass);
 			CtClass packerCtClass = pool.makeClass(packerName);
+			setSuperclass(packerCtClass, MessagePackerAccessorImpl.class);
 			setInterface(packerCtClass, MessagePacker.class);
-			addDefaultConstructor(packerCtClass);
+			addClassTypeConstructor(packerCtClass);
 			Field[] fields = getDeclaredFields(origClass);
+			MessagePacker[] packers = null;
 			if (fieldOpts != null) {
 				fields = sortFields(fields, fieldOpts);
+				packers = createMessagePackers(fieldOpts);
+			} else {
+				packers = createMessagePackers(fields);
 			}
+			setMessagePackers(origClass, packers);
 			addPackMethod(packerCtClass, origClass, fields, false);
 			Class<?> packerClass = createClass(packerCtClass);
 			LOG.debug("generated a packer class for " + origClass.getName());
@@ -101,8 +112,9 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
 			String packerName = origName + POSTFIX_TYPE_NAME_PACKER + inc();
 			checkTypeValidation(origClass);
 			CtClass packerCtClass = pool.makeClass(packerName);
+			setSuperclass(packerCtClass, MessagePackerAccessorImpl.class);
 			setInterface(packerCtClass, MessagePacker.class);
-			addDefaultConstructor(packerCtClass);
+			addClassTypeConstructor(packerCtClass);
 			addPackMethod(packerCtClass, origClass, null, true);
 			Class<?> packerClass = createClass(packerCtClass);
 			LOG.debug("generated an enum class for " + origClass.getName());
@@ -128,7 +140,7 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
 			CtClass tmplCtClass = pool.makeClass(tmplName);
 			setSuperclass(tmplCtClass, TemplateAccessorImpl.class);
 			setInterface(tmplCtClass, Template.class);
-			addDefaultConstructor(tmplCtClass);
+			addClassTypeConstructor(tmplCtClass);
 			Field[] fields = getDeclaredFields(origClass);
 			Template[] tmpls = null;
 			if (fieldOpts != null) {
@@ -166,7 +178,7 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
 			CtClass tmplCtClass = pool.makeClass(tmplName);
 			setSuperclass(tmplCtClass, TemplateAccessorImpl.class);
 			setInterface(tmplCtClass, Template.class);
-			addDefaultConstructor(tmplCtClass);
+			addClassTypeConstructor(tmplCtClass);
 			addUnpackMethod(tmplCtClass, origClass, null, true);
 			addConvertMethod(tmplCtClass, origClass, null, true);
 			Class<?> tmplClass = createClass(tmplCtClass);
@@ -279,6 +291,38 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
 		return sorted;
 	}
 
+	MessagePacker[] createMessagePackers(List<FieldOption> fieldOpts) {
+		MessagePacker[] pks = new MessagePacker[fieldOpts.size()];
+		for (int i = 0; i < pks.length; ++i) {
+			pks[i] = toMessagePacker(fieldOpts.get(i).tmpl);
+		}
+		return pks;
+	}
+
+	MessagePacker[] createMessagePackers(Field[] fields) {
+		MessagePacker[] pks = new MessagePacker[fields.length];
+		for (int i = 0; i < pks.length; ++i) {
+			pks[i] = createMessagePacker(fields[i]);
+		}
+		return pks;
+	}
+
+	MessagePacker createMessagePacker(Field field) {
+		boolean isOptional = isAnnotated(field, MessagePackOptional.class);
+		Class<?> c = field.getType();
+		MessagePacker pk = null;
+		if (List.class.isAssignableFrom(c) || Map.class.isAssignableFrom(c)) {
+			pk = createMessagePacker(field.getGenericType());
+		} else {
+			pk = createMessagePacker(c);
+		}
+		if (isOptional) {
+			return new OptionalPacker(pk);
+		} else {
+			return pk;
+		}
+	}
+
 	Template[] createTemplates(List<FieldOption> fieldOpts) {
 		Template[] tmpls = new Template[fieldOpts.size()];
 		for (int i = 0; i < tmpls.length; ++i) {
@@ -310,17 +354,17 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
 			return tmpl;
 		}
 	}
-	
+
 	private boolean isAnnotated(Field field, Class<? extends Annotation> with) {
 		return field.getAnnotation(with) != null;
 	}
 
-	private void addPackMethod(CtClass packerCtClass, Class<?> c, Field[] fs,
-			boolean isEnum) {
+	private void addPackMethod(CtClass packerCtClass, Class<?> c,
+			Field[] fields, boolean isEnum) {
 		// void pack(Packer pk, Object target) throws IOException;
 		StringBuilder sb = new StringBuilder();
 		if (!isEnum) {
-			insertPackMethodBody(sb, c, fs);
+			insertPackMethodBody(sb, c, fields);
 		} else {
 			insertOrdinalEnumPackMethodBody(sb, c);
 		}
@@ -360,52 +404,20 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
 		sb.append(String.format(STATEMENT_PACKER_PACKERMETHODBODY_01, args0));
 		Object[] args1 = new Object[] { fields.length };
 		sb.append(String.format(STATEMENT_PACKER_PACKERMETHODBODY_02, args1));
-		for (Field f : fields) {
-			insertCodeOfPackMethodCall(sb, f);
+		for (int i = 0; i < fields.length; ++i) {
+			insertCodeOfPackMethodCall(sb, fields[i], i);
 		}
 		sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET);
 	}
 
-	private void insertCodeOfPackMethodCall(StringBuilder sb, Field field) {
-		Class<?> c = field.getType();
-		if (c.isPrimitive()) {
-			; // ignore
-		} else if (c.equals(Boolean.class) || c.equals(Byte.class)
-				|| c.equals(Double.class) || c.equals(Float.class)
-				|| c.equals(Integer.class) || c.equals(Long.class)
-				|| c.equals(Short.class)) {
-			; // ignore
-		} else if (c.equals(String.class) || c.equals(BigInteger.class)
-				|| c.equals(byte[].class)) {
-			; // ignore
-		} else if (List.class.isAssignableFrom(c)
-				|| Map.class.isAssignableFrom(c)) {
-			; // ignore
-		} else if (CustomPacker.isRegistered(c)) {
-			; // ignore
-		} else if (MessagePackable.class.isAssignableFrom(c)) {
-			; // ignore
-		} else if (CustomMessage.isAnnotated(c, MessagePackMessage.class)) {
-			// @MessagePackMessage
-			MessagePacker packer = DynamicPacker.create(c);
-			CustomMessage.registerPacker(c, packer);
-		} else if (CustomMessage.isAnnotated(c, MessagePackDelegate.class)) {
-			// FIXME DelegatePacker
-			UnsupportedOperationException e = new UnsupportedOperationException(
-					"not supported yet. : " + c.getName());
-			LOG.error(e.getMessage(), e);
-			throw e;
-		} else if (CustomMessage.isAnnotated(c, MessagePackOrdinalEnum.class)) {
-			// @MessagePackOrdinalEnum
-			MessagePacker packer = DynamicOrdinalEnumPacker.create(c);
-			CustomMessage.registerPacker(c, packer);
-		} else {
-			MessageTypeException e = new MessageTypeException("unknown type: "
-					+ c.getName());
-			LOG.error(e.getMessage(), e);
-			throw e;
-		}
-		Object[] args = new Object[] { field.getName() };
+	private void insertCodeOfPackMethodCall(StringBuilder sb, Field field, int i) {
+		// _$$_packers[i].pack($1, new Integer(target.fi));
+		Class<?> type = field.getType();
+		boolean isPrim = type.isPrimitive();
+		Object[] args = new Object[] {
+				i,
+				isPrim ? "new " + getPrimToWrapperType(type).getName() + "("
+						: "", field.getName(), isPrim ? ")" : "" };
 		sb.append(String.format(STATEMENT_PACKER_PACKERMETHODBODY_03, args));
 	}
 
diff --git a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenBase.java b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenBase.java
index 95c37482..9b51c94c 100644
--- a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenBase.java
+++ b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenBase.java
@@ -7,6 +7,7 @@ import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.math.BigInteger;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -23,16 +24,46 @@ import javassist.NotFoundException;
 
 import org.msgpack.CustomConverter;
 import org.msgpack.CustomMessage;
+import org.msgpack.CustomPacker;
 import org.msgpack.MessageConvertable;
 import org.msgpack.MessagePackObject;
+import org.msgpack.MessagePackable;
+import org.msgpack.MessagePacker;
 import org.msgpack.MessageTypeException;
 import org.msgpack.MessageUnpackable;
+import org.msgpack.Packer;
 import org.msgpack.Template;
 import org.msgpack.Templates;
 import org.msgpack.Unpacker;
 import org.msgpack.annotation.MessagePackDelegate;
 import org.msgpack.annotation.MessagePackMessage;
 import org.msgpack.annotation.MessagePackOrdinalEnum;
+import org.msgpack.packer.BigIntegerPacker;
+import org.msgpack.packer.BooleanPacker;
+import org.msgpack.packer.ByteArrayPacker;
+import org.msgpack.packer.BytePacker;
+import org.msgpack.packer.DoublePacker;
+import org.msgpack.packer.FloatPacker;
+import org.msgpack.packer.IntegerPacker;
+import org.msgpack.packer.LongPacker;
+import org.msgpack.packer.OptionalPacker;
+import org.msgpack.packer.ShortPacker;
+import org.msgpack.packer.StringPacker;
+import org.msgpack.template.BigIntegerTemplate;
+import org.msgpack.template.BooleanTemplate;
+import org.msgpack.template.ByteArrayTemplate;
+import org.msgpack.template.ByteTemplate;
+import org.msgpack.template.ClassTemplate;
+import org.msgpack.template.CollectionTemplate;
+import org.msgpack.template.DoubleTemplate;
+import org.msgpack.template.FloatTemplate;
+import org.msgpack.template.IntegerTemplate;
+import org.msgpack.template.ListTemplate;
+import org.msgpack.template.LongTemplate;
+import org.msgpack.template.MapTemplate;
+import org.msgpack.template.OptionalTemplate;
+import org.msgpack.template.ShortTemplate;
+import org.msgpack.template.StringTemplate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -41,12 +72,66 @@ public class DynamicCodeGenBase implements Constants {
 	private static Logger LOG = LoggerFactory
 			.getLogger(DynamicCodeGenBase.class);
 
-	public static class MessageUnpackableConvertableTemplate implements
-			Template {
-
+	static class MessagePackablePacker implements MessagePacker {
+		@SuppressWarnings("unused")
 		private Class<?> type;
 
-		public MessageUnpackableConvertableTemplate(Class<?> type) {
+		MessagePackablePacker(Class<?> type) {
+			this.type = type;
+		}
+
+		@Override
+		public void pack(Packer packer, Object target) throws IOException {
+			MessagePackable mp = MessagePackable.class.cast(target);
+			mp.messagePack(packer);
+		}
+	}
+
+	static class ListPacker implements MessagePacker {
+		private MessagePacker elementPacker;
+
+		ListPacker(MessagePacker elementPacker) {
+			this.elementPacker = elementPacker;
+		}
+
+		@SuppressWarnings("unchecked")
+		@Override
+		public void pack(Packer packer, Object target) throws IOException {
+			List<Object> list = (List<Object>) target;
+			packer.packArray(list.size());
+			for (Iterator<Object> iter = list.iterator(); iter.hasNext();) {
+				elementPacker.pack(packer, iter.next());
+			}
+		}
+	}
+
+	static class MapPacker implements MessagePacker {
+		private MessagePacker keyPacker;
+		private MessagePacker valPacker;
+
+		MapPacker(MessagePacker keyPacker, MessagePacker valPacker) {
+			this.keyPacker = keyPacker;
+			this.valPacker = valPacker;
+		}
+
+		@SuppressWarnings("unchecked")
+		@Override
+		public void pack(Packer packer, Object target) throws IOException {
+			Map<Object, Object> map = (Map<Object, Object>) target;
+			packer.packMap(map.size());
+			for (Map.Entry<Object, Object> e : ((Map<Object, Object>) map)
+					.entrySet()) {
+				keyPacker.pack(packer, e.getKey());
+				valPacker.pack(packer, e.getValue());
+			}
+		}
+
+	}
+
+	static class MessageUnpackableConvertableTemplate implements Template {
+		private Class<?> type;
+
+		MessageUnpackableConvertableTemplate(Class<?> type) {
 			this.type = type;
 		}
 
@@ -84,13 +169,43 @@ public class DynamicCodeGenBase implements Constants {
 		}
 	}
 
-	public static interface TemplateAccessor {
+	static interface MessagePackerAccessor {
+		void setMessagePackers(MessagePacker[] packers);
+	}
+
+	static class MessagePackerAccessorImpl implements MessagePackerAccessor {
+		public Class<?> type;
+
+		public MessagePacker[] _$$_packers;
+
+		public MessagePackerAccessorImpl() {
+		}
+
+		public MessagePackerAccessorImpl(Class<?> type) {
+			this.type = type;
+		}
+
+		public void setMessagePackers(MessagePacker[] _$$_pks) {
+			_$$_packers = _$$_pks;
+		}
+	}
+
+	static interface TemplateAccessor {
 		void setTemplates(Template[] templates);
 	}
 
-	public static class TemplateAccessorImpl implements TemplateAccessor {
+	static class TemplateAccessorImpl implements TemplateAccessor {
+		public Class<?> type;
+
 		public Template[] _$$_templates;
 
+		public TemplateAccessorImpl() {
+		}
+
+		public TemplateAccessorImpl(Class<?> type) {
+			this.type = type;
+		}
+
 		public void setTemplates(Template[] _$$_tmpls) {
 			_$$_templates = _$$_tmpls;
 		}
@@ -190,11 +305,38 @@ public class DynamicCodeGenBase implements Constants {
 		newCtClass.addInterface(infCtClass);
 	}
 
-	protected void addDefaultConstructor(CtClass enhancedCtClass)
+	protected void addClassTypeConstructor(CtClass newCtClass)
+			throws CannotCompileException, NotFoundException {
+		CtConstructor newCtCons = CtNewConstructor.make(new CtClass[] { pool
+				.get(Class.class.getName()) }, new CtClass[0], newCtClass);
+		newCtClass.addConstructor(newCtCons);
+	}
+
+	protected void addDefaultConstructor(CtClass newCtClass)
 			throws CannotCompileException {
 		CtConstructor newCtCons = CtNewConstructor
-				.defaultConstructor(enhancedCtClass);
-		enhancedCtClass.addConstructor(newCtCons);
+				.defaultConstructor(newCtClass);
+		newCtClass.addConstructor(newCtCons);
+	}
+
+	protected void addMessagePackerArrayField(CtClass newCtClass)
+			throws NotFoundException, CannotCompileException {
+		CtClass acsCtClass = pool
+				.get(MessagePackerAccessorImpl.class.getName());
+		CtField pksField = acsCtClass.getDeclaredField(VARIABLE_NAME_PACKERS);
+		CtField pksField2 = new CtField(pksField.getType(), pksField.getName(),
+				newCtClass);
+		newCtClass.addField(pksField2);
+	}
+
+	protected void addSetMessagePackersMethod(CtClass newCtClass)
+			throws NotFoundException, CannotCompileException {
+		CtClass acsCtClass = pool.get(TemplateAccessorImpl.class.getName());
+		CtMethod setPksMethod = acsCtClass
+				.getDeclaredMethod(METHOD_NAME_SETMESSAGEPACKERS);
+		CtMethod setPksMethod2 = CtNewMethod.copy(setPksMethod, newCtClass,
+				null);
+		newCtClass.addMethod(setPksMethod2);
 	}
 
 	protected void addTemplateArrayField(CtClass newCtClass)
@@ -318,6 +460,139 @@ public class DynamicCodeGenBase implements Constants {
 		}
 	}
 
+	public static MessagePacker toMessagePacker(Template tmpl) {
+		if (tmpl instanceof BigIntegerTemplate) {
+			return BigIntegerPacker.getInstance();
+		} else if (tmpl instanceof BooleanTemplate) {
+			return BooleanPacker.getInstance();
+		} else if (tmpl instanceof ByteArrayTemplate) {
+			return ByteArrayPacker.getInstance();
+		} else if (tmpl instanceof ByteTemplate) {
+			return BytePacker.getInstance();
+		} else if (tmpl instanceof ClassTemplate) {
+			UnsupportedOperationException e = new UnsupportedOperationException(
+					"not supported yet.");
+			LOG.error(e.getMessage(), e);
+			throw e;
+		} else if (tmpl instanceof CollectionTemplate) {
+			UnsupportedOperationException e = new UnsupportedOperationException(
+					"not supported yet.");
+			LOG.error(e.getMessage(), e);
+			throw e;
+		} else if (tmpl instanceof DoubleTemplate) {
+			return DoublePacker.getInstance();
+		} else if (tmpl instanceof FloatTemplate) {
+			return FloatPacker.getInstance();
+		} else if (tmpl instanceof IntegerTemplate) {
+			return IntegerPacker.getInstance();
+		} else if (tmpl instanceof ListTemplate) {
+			ListTemplate t = (ListTemplate) tmpl;
+			return new ListPacker(toMessagePacker(t.getElementTemplate()));
+		} else if (tmpl instanceof LongTemplate) {
+			return LongPacker.getInstance();
+		} else if (tmpl instanceof MapTemplate) {
+			MapTemplate t = (MapTemplate) tmpl;
+			return new MapPacker(toMessagePacker(t.getKeyTemplate()),
+					toMessagePacker(t.getValueTemplate()));
+		} else if (tmpl instanceof OptionalTemplate) {
+			OptionalTemplate t = (OptionalTemplate) tmpl;
+			return new OptionalPacker(toMessagePacker(t.getElementTemplate()));
+		} else if (tmpl instanceof ShortTemplate) {
+			return ShortPacker.getInstance();
+		} else if (tmpl instanceof StringTemplate) {
+			return StringPacker.getInstance();
+		} else if (tmpl instanceof TemplateAccessorImpl) {
+			Class<?> c = ((TemplateAccessorImpl) tmpl).type;
+			if (CustomPacker.isRegistered(c)) {
+				return CustomPacker.get(c);
+			} else {
+				MessagePacker packer = DynamicPacker.create(c);
+				CustomMessage.registerPacker(c, packer);
+				return packer;
+			}
+		}
+		UnsupportedOperationException e = new UnsupportedOperationException(
+				"not supported yet.");
+		LOG.error(e.getMessage(), e);
+		throw e;
+	}
+
+	public MessagePacker createMessagePacker(Type t) {
+		if (t.getClass().equals(Class.class)) {
+			Class<?> c = (Class<?>) t;
+			if (c.equals(boolean.class) || c.equals(Boolean.class)) {
+				return BooleanPacker.getInstance();
+			} else if (c.equals(byte.class) || c.equals(Byte.class)) {
+				return BytePacker.getInstance();
+			} else if (c.equals(short.class) || c.equals(Short.class)) {
+				return ShortPacker.getInstance();
+			} else if (c.equals(int.class) || c.equals(Integer.class)) {
+				return IntegerPacker.getInstance();
+			} else if (c.equals(float.class) || c.equals(Float.class)) {
+				return FloatPacker.getInstance();
+			} else if (c.equals(long.class) || c.equals(Long.class)) {
+				return LongPacker.getInstance();
+			} else if (c.equals(double.class) || c.equals(Double.class)) {
+				return DoublePacker.getInstance();
+			} else if (c.equals(String.class)) {
+				return StringPacker.getInstance();
+			} else if (c.equals(BigInteger.class)) {
+				return BigIntegerPacker.getInstance();
+			} else if (CustomPacker.isRegistered(c)) {
+				return CustomPacker.get(c);
+			} else if (CustomMessage.isAnnotated(c, MessagePackMessage.class)) {
+				// @MessagePackMessage
+				MessagePacker packer = DynamicPacker.create(c);
+				CustomMessage.registerPacker(c, packer);
+				return packer;
+			} else if (CustomMessage.isAnnotated(c, MessagePackDelegate.class)) {
+				// FIXME DelegatePacker
+				UnsupportedOperationException e = new UnsupportedOperationException(
+						"not supported yet. : " + c.getName());
+				LOG.error(e.getMessage(), e);
+				throw e;
+			} else if (CustomMessage.isAnnotated(c,
+					MessagePackOrdinalEnum.class)) {
+				// @MessagePackOrdinalEnum
+				MessagePacker packer = DynamicOrdinalEnumPacker.create(c);
+				CustomMessage.registerPacker(c, packer);
+				return packer;
+			} else if (MessagePackable.class.isAssignableFrom(c)) {
+				MessagePacker packer = new MessagePackablePacker(c);
+				CustomMessage.registerPacker(c, packer);
+				return packer;
+			} else {
+				throw new MessageTypeException("Type error: "
+						+ ((Class<?>) t).getName());
+			}
+		} else if (t instanceof GenericArrayType) {
+			GenericArrayType gat = (GenericArrayType) t;
+			Type gct = gat.getGenericComponentType();
+			if (gct.equals(byte.class)) {
+				return ByteArrayPacker.getInstance();
+			} else {
+				throw new DynamicCodeGenException("Not supported yet: " + gat);
+			}
+		} else if (t instanceof ParameterizedType) {
+			ParameterizedType pt = (ParameterizedType) t;
+			Class<?> rawType = (Class<?>) pt.getRawType();
+			if (rawType.equals(List.class)) {
+				Type[] ats = pt.getActualTypeArguments();
+				return new ListPacker(createMessagePacker(ats[0]));
+			} else if (rawType.equals(Map.class)) {
+				Type[] ats = pt.getActualTypeArguments();
+				return new MapPacker(createMessagePacker(ats[0]),
+						createMessagePacker(ats[1]));
+			} else {
+				throw new DynamicCodeGenException("Type error: "
+						+ t.getClass().getName());
+			}
+		} else {
+			throw new DynamicCodeGenException("Type error: "
+					+ t.getClass().getName());
+		}
+	}
+
 	public Template createTemplate(Type t) {
 		if (t.getClass().equals(Class.class)) {
 			Class<?> c = (Class<?>) t;
diff --git a/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumConverter.java b/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumConverter.java
index 648b4f81..7f5db66f 100644
--- a/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumConverter.java
+++ b/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumConverter.java
@@ -4,14 +4,6 @@ import org.msgpack.MessageConverter;
 
 public class DynamicOrdinalEnumConverter {
 	public static MessageConverter create(Class<?> c) {
-		try {
-			DynamicCodeGen gen = DynamicCodeGen.getInstance();
-			Class<?> unpackerClass = gen.generateOrdinalEnumTemplateClass(c);
-			return (MessageConverter) unpackerClass.newInstance();
-		} catch (InstantiationException e) {
-			throw new DynamicCodeGenException(e.getMessage(), e);
-		} catch (IllegalAccessException e) {
-			throw new DynamicCodeGenException(e.getMessage(), e);
-		}
+		return DynamicOrdinalEnumTemplate.create(c);
 	}
 }
diff --git a/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumPacker.java b/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumPacker.java
index 98f4a397..101b3f1a 100644
--- a/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumPacker.java
+++ b/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumPacker.java
@@ -1,17 +1,34 @@
 package org.msgpack.util.codegen;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
 import org.msgpack.MessagePacker;
+import org.msgpack.util.codegen.DynamicCodeGenBase.MessagePackerAccessor;
 
 public class DynamicOrdinalEnumPacker {
 	public static MessagePacker create(Class<?> c) {
 		try {
 			DynamicCodeGen gen = DynamicCodeGen.getInstance();
 			Class<?> packerClass = gen.generateOrdinalEnumPackerClass(c);
-			return (MessagePacker) packerClass.newInstance();
+			Constructor<?> cons = packerClass
+					.getDeclaredConstructor(new Class[] { Class.class });
+			Object obj = cons.newInstance(new Object[] { c });
+			((MessagePackerAccessor) obj).setMessagePackers(gen
+					.getMessagePackers(c));
+			return (MessagePacker) obj;
 		} catch (InstantiationException e) {
 			throw new DynamicCodeGenException(e.getMessage(), e);
 		} catch (IllegalAccessException e) {
 			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (SecurityException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (NoSuchMethodException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (IllegalArgumentException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (InvocationTargetException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
 		}
 	}
 }
diff --git a/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumTemplate.java b/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumTemplate.java
index c2346837..6a0287a3 100644
--- a/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumTemplate.java
+++ b/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumTemplate.java
@@ -1,17 +1,33 @@
 package org.msgpack.util.codegen;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
 import org.msgpack.Template;
+import org.msgpack.util.codegen.DynamicCodeGenBase.TemplateAccessor;
 
 public class DynamicOrdinalEnumTemplate {
 	public static Template create(Class<?> c) {
 		try {
 			DynamicCodeGen gen = DynamicCodeGen.getInstance();
 			Class<?> tmplClass = gen.generateOrdinalEnumTemplateClass(c);
-			return (Template) tmplClass.newInstance();
+			Constructor<?> cons = tmplClass
+					.getDeclaredConstructor(new Class[] { Class.class });
+			Object obj = cons.newInstance(new Object[] { c });
+			((TemplateAccessor) obj).setTemplates(gen.getTemplates(c));
+			return (Template) obj;
 		} catch (InstantiationException e) {
 			throw new DynamicCodeGenException(e.getMessage(), e);
 		} catch (IllegalAccessException e) {
 			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (SecurityException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (NoSuchMethodException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (IllegalArgumentException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (InvocationTargetException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
 		}
 	}
 }
diff --git a/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumUnpacker.java b/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumUnpacker.java
index edad9a82..7b839003 100644
--- a/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumUnpacker.java
+++ b/java/src/main/java/org/msgpack/util/codegen/DynamicOrdinalEnumUnpacker.java
@@ -4,14 +4,6 @@ import org.msgpack.MessageUnpacker;
 
 public class DynamicOrdinalEnumUnpacker {
 	public static MessageUnpacker create(Class<?> c) {
-		try {
-			DynamicCodeGen gen = DynamicCodeGen.getInstance();
-			Class<?> unpackerClass = gen.generateOrdinalEnumTemplateClass(c);
-			return (MessageUnpacker) unpackerClass.newInstance();
-		} catch (InstantiationException e) {
-			throw new DynamicCodeGenException(e.getMessage(), e);
-		} catch (IllegalAccessException e) {
-			throw new DynamicCodeGenException(e.getMessage(), e);
-		}
+		return DynamicOrdinalEnumTemplate.create(c);
 	}
 }
diff --git a/java/src/main/java/org/msgpack/util/codegen/DynamicPacker.java b/java/src/main/java/org/msgpack/util/codegen/DynamicPacker.java
index fbd019dd..65bcc967 100644
--- a/java/src/main/java/org/msgpack/util/codegen/DynamicPacker.java
+++ b/java/src/main/java/org/msgpack/util/codegen/DynamicPacker.java
@@ -1,8 +1,11 @@
 package org.msgpack.util.codegen;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.util.List;
 
 import org.msgpack.MessagePacker;
+import org.msgpack.util.codegen.DynamicCodeGenBase.MessagePackerAccessor;
 
 public class DynamicPacker {
 
@@ -14,11 +17,24 @@ public class DynamicPacker {
 		try {
 			DynamicCodeGen gen = DynamicCodeGen.getInstance();
 			Class<?> packerClass = gen.generateMessagePackerClass(c, fieldOpts);
-			return (MessagePacker) packerClass.newInstance();
+			Constructor<?> cons = packerClass
+					.getDeclaredConstructor(new Class[] { Class.class });
+			Object obj = cons.newInstance(new Object[] { c });
+			((MessagePackerAccessor) obj).setMessagePackers(gen
+					.getMessagePackers(c));
+			return (MessagePacker) obj;
 		} catch (InstantiationException e) {
 			throw new DynamicCodeGenException(e.getMessage(), e);
 		} catch (IllegalAccessException e) {
 			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (SecurityException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (NoSuchMethodException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (IllegalArgumentException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (InvocationTargetException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
 		}
 	}
 }
diff --git a/java/src/main/java/org/msgpack/util/codegen/DynamicTemplate.java b/java/src/main/java/org/msgpack/util/codegen/DynamicTemplate.java
index 673c344e..7aeffa94 100644
--- a/java/src/main/java/org/msgpack/util/codegen/DynamicTemplate.java
+++ b/java/src/main/java/org/msgpack/util/codegen/DynamicTemplate.java
@@ -1,5 +1,7 @@
 package org.msgpack.util.codegen;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.util.List;
 
 import org.msgpack.Template;
@@ -14,13 +16,23 @@ public class DynamicTemplate {
 		try {
 			DynamicCodeGen gen = DynamicCodeGen.getInstance();
 			Class<?> tmplClass = gen.generateTemplateClass(c, fieldOpts);
-			Object obj = tmplClass.newInstance();
+			Constructor<?> cons = tmplClass
+					.getDeclaredConstructor(new Class[] { Class.class });
+			Object obj = cons.newInstance(new Object[] { c });
 			((TemplateAccessor) obj).setTemplates(gen.getTemplates(c));
 			return (Template) obj;
 		} catch (InstantiationException e) {
 			throw new DynamicCodeGenException(e.getMessage(), e);
 		} catch (IllegalAccessException e) {
 			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (SecurityException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (NoSuchMethodException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (IllegalArgumentException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
+		} catch (InvocationTargetException e) {
+			throw new DynamicCodeGenException(e.getMessage(), e);
 		}
 	}
 }