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 e0cfc1ec..fc6650f2 100644
--- a/java/src/main/java/org/msgpack/util/codegen/Constants.java
+++ b/java/src/main/java/org/msgpack/util/codegen/Constants.java
@@ -78,7 +78,7 @@ public interface Constants {
 
 	String STATEMENT_TMPL_UNPACKERMETHODBODY_01 = "%s _$$_t = new %s(); ";
 
-	String STATEMENT_TMPL_UNPACKERMETHODBODY_02 = "$1.unpackArray(); ";
+	String STATEMENT_TMPL_UNPACKERMETHODBODY_02 = "int _$$_L = $1.unpackArray(); ";
 
 	String STATEMENT_TMPL_UNPACKERMETHODBODY_03 = "_$$_t.%s = %s(%s)_$$_templates[%d].unpack($1)%s; ";
 
@@ -88,6 +88,12 @@ public interface Constants {
 
 	String STATEMENT_TMPL_UNPACKERMETHODBODY_06 = "return %s.class.getEnumConstants()[i]; ";
 
+	String STATEMENT_TMPL_UNPACKERMETHODBODY_07 = "if(_$$_L <= %d) { throw new org.msgpack.MessageTypeException(); } ";
+
+	String STATEMENT_TMPL_UNPACKERMETHODBODY_08 = "if(_$$_L > %d && !$1.tryUnpackNull()) ";
+
+	String STATEMENT_TMPL_UNPACKERMETHODBODY_09 = "for(int _$$_n = %d; _$$_n < _$$_L; _$$_n++) { $1.unpackObject(); } ";
+
 	String STATEMENT_TMPL_CONVERTMETHODBODY_01 = "%s _$$_ary = $1.asArray(); ";
 
 	String STATEMENT_TMPL_CONVERTMETHODBODY_02 = "_$$_t.%s = %s(%s)_$$_templates[%d].convert(_$$_ary[%d])%s; ";
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 f54f8090..edd23d80 100644
--- a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java
+++ b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java
@@ -262,6 +262,7 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
 			tmpl = createTemplate(c);
 		}
 		if (isOptional) {
+			// for pack
 			return new OptionalTemplate(tmpl);
 		} else {
 			return tmpl;
@@ -393,7 +394,7 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
 		String typeName = classToString(type);
 		Object[] args0 = new Object[] { typeName, typeName };
 		sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_01, args0));
-		// $1.unpackArray();
+		// int _$$_L = $1.unpackArray();
 		Object[] args1 = new Object[0];
 		sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_02, args1));
 		insertCodeOfUnpackMethodCalls(sb, fields);
@@ -407,10 +408,27 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
 		for (int i = 0; i < fields.length; ++i) {
 			insertCodeOfUnpackMethodCall(sb, fields[i], i);
 		}
+		insertCodeOfUnpackTrails(sb, fields.length);
 	}
 
 	private void insertCodeOfUnpackMethodCall(StringBuilder sb, Field field,
 			int i) {
+		boolean isOptional = isAnnotated(field, MessagePackOptional.class);
+
+		if(isOptional) {
+			// if(_$$_L > i && !$1.tryUnpackNull()) {
+			Object[] args0 = new Object[] { i };
+			sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_08, args0));
+			sb.append(CHAR_NAME_LEFT_CURLY_BRACKET);
+
+		} else {
+			// if(_$$_L <= i) {
+			// 	throw new MessageTypeException();
+			// }
+			Object[] args0 = new Object[] { i };
+			sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_07, args0));
+		}
+
 		// target.fi = ((Integer)_$$_tmpls[i].unpack(_$$_pk)).intValue();
 		Class<?> returnType = field.getType();
 		boolean isPrim = returnType.isPrimitive();
@@ -423,6 +441,19 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
 				isPrim ? ")." + getPrimTypeValueMethodName(returnType) + "()"
 						: "" };
 		sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_03, args));
+
+		if(isOptional) {
+			// }
+			sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET);
+		}
+	}
+
+	private void insertCodeOfUnpackTrails(StringBuilder sb, int length) {
+		// for(int _$$_n = length; _$$_n < _$$_L; _$$_n++) {
+		//     $1.unpackObject();
+		// }
+		Object[] args0 = new Object[] { length };
+		sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_09, args0));
 	}
 
 	private void insertOrdinalEnumUnpackMethodBody(StringBuilder sb,