Repository: apache/dubbo-go-hessian2
Pull request #217 (2020-08-09 01:00:46)

merge for v1.6.1

**What this PR does**:
merge for v1.6.1


**Does this PR introduce a user-facing change?**:
```release-note
- add java8 time object support
- support test golang encoding data in java 
- Fix []byte field decoding issue
```


Patch:
diff --git a/.travis.yml b/.travis.yml
index 5442ab1..36c42e9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,7 +13,8 @@ os: linux
 dist: xenial
 
 script:
-  - mvn clean package -f test_hessian/pom.xml
+  - mvn clean package -DskipTests=true -f test_hessian/pom.xml
+  - mvn test -f test_hessian/pom.xml
   - mvn clean package -f test_dubbo/pom.xml
   - go fmt && [[ -z `git status -s` ]]
   - sh before_validate_license.sh
diff --git a/binary.go b/binary.go
index 1cdea45..a30af8d 100644
--- a/binary.go
+++ b/binary.go
@@ -26,6 +26,14 @@ import (
 	perrors "github.com/pkg/errors"
 )
 
+// binaryTag check whether the given tag is a binary tag
+func binaryTag(tag byte) bool {
+	return (tag >= BC_BINARY_DIRECT && tag <= INT_DIRECT_MAX) ||
+		(tag >= BC_BINARY_SHORT && tag <= byte(0x37)) ||
+		tag == BC_BINARY_CHUNK ||
+		tag == BC_BINARY
+}
+
 /////////////////////////////////////////
 // Binary, []byte
 /////////////////////////////////////////
diff --git a/java8_time.go b/java8_time.go
new file mode 100644
index 0000000..d4a72b1
--- /dev/null
+++ b/java8_time.go
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package hessian
+
+import (
+	"github.com/apache/dubbo-go-hessian2/java8_time"
+)
+
+func init() {
+	RegisterPOJO(&java8_time.Year{Year: 2020})
+	RegisterPOJO(&java8_time.YearMonth{Month: 2020, Year: 6})
+	RegisterPOJO(&java8_time.Period{Years: 2020, Months: 6, Days: 6})
+	RegisterPOJO(&java8_time.LocalDate{Year: 2020, Month: 6, Day: 6})
+	RegisterPOJO(&java8_time.LocalTime{Hour: 6, Minute: 6, Second: 0, Nano: 0})
+	RegisterPOJO(&java8_time.LocalDateTime{Date: java8_time.LocalDate{Year: 2020, Month: 6, Day: 6}, Time: java8_time.LocalTime{Hour: 6, Minute: 6}})
+	RegisterPOJO(&java8_time.MonthDay{Month: 6, Day: 6})
+	RegisterPOJO(&java8_time.Duration{Second: 0, Nano: 0})
+	RegisterPOJO(&java8_time.Instant{Seconds: 100, Nanos: 0})
+}
diff --git a/java8_time/duration.go b/java8_time/duration.go
new file mode 100644
index 0000000..ee01d54
--- /dev/null
+++ b/java8_time/duration.go
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java8_time
+
+type Duration struct {
+	Second int64 `hessian:"second"`
+	Nano   int32 `hessian:"nano"`
+}
+
+func (Duration) JavaClassName() string {
+	return "com.alibaba.com.caucho.hessian.io.java8.DurationHandle"
+}
+
+func (Duration) Error() string {
+	return "encode Duration error"
+}
diff --git a/java8_time/instant.go b/java8_time/instant.go
new file mode 100644
index 0000000..09e7cce
--- /dev/null
+++ b/java8_time/instant.go
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java8_time
+
+type Instant struct {
+	Seconds int64 `hessian:"seconds"`
+	Nanos   int32 `hessian:"nanos"`
+}
+
+func (Instant) JavaClassName() string {
+	return "com.alibaba.com.caucho.hessian.io.java8.InstantHandle"
+}
+
+func (Instant) Error() string {
+	return "encode Instant error"
+}
diff --git a/java8_time/local_date.go b/java8_time/local_date.go
new file mode 100644
index 0000000..e71281e
--- /dev/null
+++ b/java8_time/local_date.go
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java8_time
+
+type LocalDate struct {
+	Year  int32 `hessian:"year"`
+	Month int32 `hessian:"month"`
+	Day   int32 `hessian:"day"`
+}
+
+func (LocalDate) JavaClassName() string {
+	return "com.alibaba.com.caucho.hessian.io.java8.LocalDateHandle"
+}
+
+func (LocalDate) Error() string {
+	return "encode LocalDate error"
+}
diff --git a/java8_time/local_date_time.go b/java8_time/local_date_time.go
new file mode 100644
index 0000000..2c0c20a
--- /dev/null
+++ b/java8_time/local_date_time.go
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java8_time
+
+type LocalDateTime struct {
+	Date LocalDate `hessian:"date"`
+	Time LocalTime `hessian:"time"`
+}
+
+func (LocalDateTime) JavaClassName() string {
+	return "com.alibaba.com.caucho.hessian.io.java8.LocalDateTimeHandle"
+}
+
+func (LocalDateTime) Error() string {
+	return "encode LocalDateTime error"
+}
diff --git a/java8_time/local_time.go b/java8_time/local_time.go
new file mode 100644
index 0000000..408e104
--- /dev/null
+++ b/java8_time/local_time.go
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java8_time
+
+type LocalTime struct {
+	Hour   int32 `hessian:"hour"`
+	Minute int32 `hessian:"minute"`
+	Second int32 `hessian:"second"`
+	Nano   int32 `hessian:"nano"`
+}
+
+func (LocalTime) JavaClassName() string {
+	return "com.alibaba.com.caucho.hessian.io.java8.LocalTimeHandle"
+}
+
+func (LocalTime) Error() string {
+	return "encode LocalTime error"
+}
diff --git a/java8_time/month_day.go b/java8_time/month_day.go
new file mode 100644
index 0000000..0540e61
--- /dev/null
+++ b/java8_time/month_day.go
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java8_time
+
+type MonthDay struct {
+	Month int32 `hessian:"month"`
+	Day   int32 `hessian:"day"`
+}
+
+func (MonthDay) JavaClassName() string {
+	return "com.alibaba.com.caucho.hessian.io.java8.MonthDayHandle"
+}
+
+func (MonthDay) Error() string {
+	return "encode MonthDay error"
+}
diff --git a/java8_time/period.go b/java8_time/period.go
new file mode 100644
index 0000000..a95df3c
--- /dev/null
+++ b/java8_time/period.go
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package java8_time
+
+//java8-time java.time.Period
+type Period struct {
+	Days   int32 `hessian:"days"`
+	Months int32 `hessian:"months"`
+	Years  int32 `hessian:"years"`
+}
+
+func (Period) JavaClassName() string {
+	return "com.alibaba.com.caucho.hessian.io.java8.PeriodHandle"
+}
+
+func (Period) Error() string {
+	return "encode Period error"
+}
diff --git a/java8_time/year.go b/java8_time/year.go
new file mode 100644
index 0000000..041e242
--- /dev/null
+++ b/java8_time/year.go
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package java8_time
+
+//java8-time java.time.Year
+type Year struct {
+	Year int32 `hessian:"year"`
+}
+
+func (Year) JavaClassName() string {
+	return "com.alibaba.com.caucho.hessian.io.java8.YearHandle"
+}
+
+func (Year) Error() string {
+	return "encode Year error"
+}
diff --git a/java8_time/year_month.go b/java8_time/year_month.go
new file mode 100644
index 0000000..3f07a13
--- /dev/null
+++ b/java8_time/year_month.go
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package java8_time
+
+//java8-time java.time.YearMonth
+type YearMonth struct {
+	Month int32 `hessian:"month"`
+	Year  int32 `hessian:"year"`
+}
+
+func (YearMonth) JavaClassName() string {
+	return "com.alibaba.com.caucho.hessian.io.java8.YearMonthHandle"
+}
+
+func (YearMonth) Error() string {
+	return "encode YearMonth error"
+}
diff --git a/java_exception/annotation_type_mismatch_exception.go b/java_exception/annotation_type_mismatch_exception.go
index cbd2301..a3e702c 100644
--- a/java_exception/annotation_type_mismatch_exception.go
+++ b/java_exception/annotation_type_mismatch_exception.go
@@ -46,4 +46,4 @@ func (AnnotationTypeMismatchException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e AnnotationTypeMismatchException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/array_index_out_of_bounds_exception.go b/java_exception/array_index_out_of_bounds_exception.go
index 0a09ed6..6555cd4 100644
--- a/java_exception/array_index_out_of_bounds_exception.go
+++ b/java_exception/array_index_out_of_bounds_exception.go
@@ -44,4 +44,4 @@ func (ArrayIndexOutOfBoundsException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e ArrayIndexOutOfBoundsException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/backing_store_exception.go b/java_exception/backing_store_exception.go
index 3f2e4ce..72d5ade 100644
--- a/java_exception/backing_store_exception.go
+++ b/java_exception/backing_store_exception.go
@@ -44,4 +44,4 @@ func (BackingStoreException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e BackingStoreException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/broken_barrier_exception.go b/java_exception/broken_barrier_exception.go
index 44c24e0..c018432 100644
--- a/java_exception/broken_barrier_exception.go
+++ b/java_exception/broken_barrier_exception.go
@@ -44,4 +44,4 @@ func (BrokenBarrierException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e BrokenBarrierException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/cancellation_exception.go b/java_exception/cancellation_exception.go
index fddc8df..be7be99 100644
--- a/java_exception/cancellation_exception.go
+++ b/java_exception/cancellation_exception.go
@@ -44,4 +44,4 @@ func (CancellationException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e CancellationException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/class_not_found_exception.go b/java_exception/class_not_found_exception.go
index 69eab81..1963256 100644
--- a/java_exception/class_not_found_exception.go
+++ b/java_exception/class_not_found_exception.go
@@ -45,4 +45,4 @@ func (ClassNotFoundException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e ClassNotFoundException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/classc_cast_exception.go b/java_exception/classc_cast_exception.go
index 4c6d5a2..11fd796 100644
--- a/java_exception/classc_cast_exception.go
+++ b/java_exception/classc_cast_exception.go
@@ -44,4 +44,4 @@ func (ClassCastException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e ClassCastException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/clone_not_supported_exception.go b/java_exception/clone_not_supported_exception.go
index e9ef78b..ee1abd0 100644
--- a/java_exception/clone_not_supported_exception.go
+++ b/java_exception/clone_not_supported_exception.go
@@ -48,4 +48,4 @@ func (CloneNotSupportedException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e CloneNotSupportedException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/completion_exception.go b/java_exception/completion_exception.go
index e55395b..7accd5e 100644
--- a/java_exception/completion_exception.go
+++ b/java_exception/completion_exception.go
@@ -44,4 +44,4 @@ func NewCompletionException(detailMessage string) *CompletionException {
 // equals to getStackTrace in java
 func (e CompletionException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/concurrent_modification_exception.go b/java_exception/concurrent_modification_exception.go
index 716bf54..4f50854 100644
--- a/java_exception/concurrent_modification_exception.go
+++ b/java_exception/concurrent_modification_exception.go
@@ -44,4 +44,4 @@ func NewConcurrentModificationException(detailMessage string) *ConcurrentModific
 // equals to getStackTrace in java
 func (e ConcurrentModificationException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/data_format_exception.go b/java_exception/data_format_exception.go
index 4154798..e4b0e23 100644
--- a/java_exception/data_format_exception.go
+++ b/java_exception/data_format_exception.go
@@ -44,4 +44,4 @@ func (DataFormatException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e DataFormatException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/date_time_exception.go b/java_exception/date_time_exception.go
index 6607ef8..6d0f0e8 100644
--- a/java_exception/date_time_exception.go
+++ b/java_exception/date_time_exception.go
@@ -44,4 +44,4 @@ func (DateTimeException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e DateTimeException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/date_time_parse_exception.go b/java_exception/date_time_parse_exception.go
index 3fc4f15..4cb7247 100644
--- a/java_exception/date_time_parse_exception.go
+++ b/java_exception/date_time_parse_exception.go
@@ -46,4 +46,4 @@ func (DateTimeParseException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e DateTimeParseException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/dubbo_generic_exception.go b/java_exception/dubbo_generic_exception.go
index d6c4a9c..4acde47 100644
--- a/java_exception/dubbo_generic_exception.go
+++ b/java_exception/dubbo_generic_exception.go
@@ -46,4 +46,4 @@ func (DubboGenericException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e DubboGenericException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/duplicate_format_flags_exception.go b/java_exception/duplicate_format_flags_exception.go
index 23e1798..b3358ae 100644
--- a/java_exception/duplicate_format_flags_exception.go
+++ b/java_exception/duplicate_format_flags_exception.go
@@ -50,4 +50,4 @@ func NewDuplicateFormatFlagsException(detailMessage string) *DuplicateFormatFlag
 // equals to getStackTrace in java
 func (e DuplicateFormatFlagsException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/empty_stack_exception.go b/java_exception/empty_stack_exception.go
index 21dfb0c..a2f516c 100644
--- a/java_exception/empty_stack_exception.go
+++ b/java_exception/empty_stack_exception.go
@@ -44,4 +44,4 @@ func NewEmptyStackException(detailMessage string) *EmptyStackException {
 // equals to getStackTrace in java
 func (e EmptyStackException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/enum_constant_not_present_exception.go b/java_exception/enum_constant_not_present_exception.go
index c2fcb85..c8a5aa6 100644
--- a/java_exception/enum_constant_not_present_exception.go
+++ b/java_exception/enum_constant_not_present_exception.go
@@ -46,4 +46,4 @@ func (EnumConstantNotPresentException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e EnumConstantNotPresentException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/eof_exception.go b/java_exception/eof_exception.go
index 4d973ee..25127f8 100644
--- a/java_exception/eof_exception.go
+++ b/java_exception/eof_exception.go
@@ -44,4 +44,4 @@ func (EOFException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e EOFException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/execution_exception.go b/java_exception/execution_exception.go
index e7b8fef..f57789b 100644
--- a/java_exception/execution_exception.go
+++ b/java_exception/execution_exception.go
@@ -44,4 +44,4 @@ func (ExecutionException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e ExecutionException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/file_not_found_exception.go b/java_exception/file_not_found_exception.go
index 5aa2197..8fcb6ca 100644
--- a/java_exception/file_not_found_exception.go
+++ b/java_exception/file_not_found_exception.go
@@ -44,4 +44,4 @@ func (FileNotFoundException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e FileNotFoundException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/formatter_closed_exception.go b/java_exception/formatter_closed_exception.go
index b8ccfee..784339a 100644
--- a/java_exception/formatter_closed_exception.go
+++ b/java_exception/formatter_closed_exception.go
@@ -44,4 +44,4 @@ func (FormatterClosedException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e FormatterClosedException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/illegal_access_exception.go b/java_exception/illegal_access_exception.go
index 70070d8..47db075 100644
--- a/java_exception/illegal_access_exception.go
+++ b/java_exception/illegal_access_exception.go
@@ -44,4 +44,4 @@ func (IllegalAccessException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e IllegalAccessException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/illegal_argument_exception.go b/java_exception/illegal_argument_exception.go
index 004358f..85db37b 100644
--- a/java_exception/illegal_argument_exception.go
+++ b/java_exception/illegal_argument_exception.go
@@ -40,7 +40,8 @@ func (e IllegalArgumentException) Error() string {
 func (IllegalArgumentException) JavaClassName() string {
 	return "java.lang.IllegalArgumentException"
 }
+
 // equals to getStackTrace in java
 func (e IllegalArgumentException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/illegal_classFormat_exception.go b/java_exception/illegal_classFormat_exception.go
index 6303651..acb79b2 100644
--- a/java_exception/illegal_classFormat_exception.go
+++ b/java_exception/illegal_classFormat_exception.go
@@ -44,4 +44,4 @@ func (IllegalClassFormatException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e IllegalClassFormatException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/illegal_format_code_point_exception.go b/java_exception/illegal_format_code_point_exception.go
index b61fa8d..3efd4d7 100644
--- a/java_exception/illegal_format_code_point_exception.go
+++ b/java_exception/illegal_format_code_point_exception.go
@@ -47,4 +47,4 @@ func (IllegalFormatCodePointException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e IllegalFormatCodePointException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/illegal_format_conversion_exception.go b/java_exception/illegal_format_conversion_exception.go
index 96642c8..1ce2788 100644
--- a/java_exception/illegal_format_conversion_exception.go
+++ b/java_exception/illegal_format_conversion_exception.go
@@ -48,4 +48,4 @@ func NewIllegalFormatConversionException(detailMessage string) *IllegalFormatCon
 // equals to getStackTrace in java
 func (e IllegalFormatConversionException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/illegal_format_flags_exception.go b/java_exception/illegal_format_flags_exception.go
index d844f83..a3ee18b 100644
--- a/java_exception/illegal_format_flags_exception.go
+++ b/java_exception/illegal_format_flags_exception.go
@@ -47,4 +47,4 @@ func (IllegalFormatFlagsException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e IllegalFormatFlagsException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/illegal_format_precision_exception.go b/java_exception/illegal_format_precision_exception.go
index 336e25c..d57bba0 100644
--- a/java_exception/illegal_format_precision_exception.go
+++ b/java_exception/illegal_format_precision_exception.go
@@ -47,4 +47,4 @@ func (IllegalFormatPrecisionException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e IllegalFormatPrecisionException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/illegal_format_width_exception.go b/java_exception/illegal_format_width_exception.go
index 680ccfc..e32f200 100644
--- a/java_exception/illegal_format_width_exception.go
+++ b/java_exception/illegal_format_width_exception.go
@@ -47,4 +47,4 @@ func NewIllegalFormatWidthException(w int) *IllegalFormatWidthException {
 // equals to getStackTrace in java
 func (e IllegalFormatWidthException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/illegal_monitor_state_exception.go b/java_exception/illegal_monitor_state_exception.go
index 2f2a254..4374afc 100644
--- a/java_exception/illegal_monitor_state_exception.go
+++ b/java_exception/illegal_monitor_state_exception.go
@@ -44,4 +44,4 @@ func (IllegalMonitorStateException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e IllegalMonitorStateException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/illegal_state_exception.go b/java_exception/illegal_state_exception.go
index 21d1e94..88aa7c3 100644
--- a/java_exception/illegal_state_exception.go
+++ b/java_exception/illegal_state_exception.go
@@ -44,4 +44,4 @@ func (IllegalStateException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e IllegalStateException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/illegal_thread_state_exception.go b/java_exception/illegal_thread_state_exception.go
index a800e60..8aacdc5 100644
--- a/java_exception/illegal_thread_state_exception.go
+++ b/java_exception/illegal_thread_state_exception.go
@@ -44,4 +44,4 @@ func (IllegalThreadStateException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e IllegalThreadStateException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/illformed_locale_exception.go b/java_exception/illformed_locale_exception.go
index 6c78812..baf9436 100644
--- a/java_exception/illformed_locale_exception.go
+++ b/java_exception/illformed_locale_exception.go
@@ -45,4 +45,4 @@ func NewIllformedLocaleException(detailMessage string) *IllformedLocaleException
 // equals to getStackTrace in java
 func (e IllformedLocaleException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/incomplete_annotation_exception.go b/java_exception/incomplete_annotation_exception.go
index 6217b99..6543d36 100644
--- a/java_exception/incomplete_annotation_exception.go
+++ b/java_exception/incomplete_annotation_exception.go
@@ -46,4 +46,4 @@ func (IncompleteAnnotationException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e IncompleteAnnotationException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/index_out_of_bounds_exception.go b/java_exception/index_out_of_bounds_exception.go
index 0bbf1d3..bd5349d 100644
--- a/java_exception/index_out_of_bounds_exception.go
+++ b/java_exception/index_out_of_bounds_exception.go
@@ -44,4 +44,4 @@ func (IndexOutOfBoundsException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e IndexOutOfBoundsException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/input_mismatch_exception.go b/java_exception/input_mismatch_exception.go
index 4f6d075..44e0eca 100644
--- a/java_exception/input_mismatch_exception.go
+++ b/java_exception/input_mismatch_exception.go
@@ -44,4 +44,4 @@ func (InputMismatchException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e InputMismatchException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/instantiation_exception.go b/java_exception/instantiation_exception.go
index ac744fc..eb6de69 100644
--- a/java_exception/instantiation_exception.go
+++ b/java_exception/instantiation_exception.go
@@ -44,4 +44,4 @@ func (InstantiationException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e InstantiationException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/interrupted_exception.go b/java_exception/interrupted_exception.go
index 8f26e56..00495b7 100644
--- a/java_exception/interrupted_exception.go
+++ b/java_exception/interrupted_exception.go
@@ -47,4 +47,4 @@ func (InterruptedException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e InterruptedException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/interrupted_io_exception.go b/java_exception/interrupted_io_exception.go
index deb4e2d..7ecb844 100644
--- a/java_exception/interrupted_io_exception.go
+++ b/java_exception/interrupted_io_exception.go
@@ -48,4 +48,4 @@ func (InterruptedIOException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e InterruptedIOException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/invalid_class_exception.go b/java_exception/invalid_class_exception.go
index 3dbffdf..ca97120 100644
--- a/java_exception/invalid_class_exception.go
+++ b/java_exception/invalid_class_exception.go
@@ -52,4 +52,4 @@ func (InvalidClassException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e InvalidClassException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/invalid_object_exception.go b/java_exception/invalid_object_exception.go
index 35cf767..334116e 100644
--- a/java_exception/invalid_object_exception.go
+++ b/java_exception/invalid_object_exception.go
@@ -44,4 +44,4 @@ func (InvalidObjectException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e InvalidObjectException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/invalid_preferences_format_exception.go b/java_exception/invalid_preferences_format_exception.go
index 8e83f88..92c9600 100644
--- a/java_exception/invalid_preferences_format_exception.go
+++ b/java_exception/invalid_preferences_format_exception.go
@@ -44,4 +44,4 @@ func (InvalidPreferencesFormatException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e InvalidPreferencesFormatException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/invalid_properties_format_exception.go b/java_exception/invalid_properties_format_exception.go
index 705e942..56a4cc7 100644
--- a/java_exception/invalid_properties_format_exception.go
+++ b/java_exception/invalid_properties_format_exception.go
@@ -44,4 +44,4 @@ func (InvalidPropertiesFormatException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e InvalidPropertiesFormatException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/invocation_target_exception.go b/java_exception/invocation_target_exception.go
index 55bb113..d530ad0 100644
--- a/java_exception/invocation_target_exception.go
+++ b/java_exception/invocation_target_exception.go
@@ -45,4 +45,4 @@ func (InvocationTargetException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e InvocationTargetException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/io_exception.go b/java_exception/io_exception.go
index 94333c7..01f4ece 100644
--- a/java_exception/io_exception.go
+++ b/java_exception/io_exception.go
@@ -44,4 +44,4 @@ func (IOException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e IOException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/jar_exception.go b/java_exception/jar_exception.go
index 899a101..2a1ad50 100644
--- a/java_exception/jar_exception.go
+++ b/java_exception/jar_exception.go
@@ -44,4 +44,4 @@ func (JarException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e JarException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/lambda_conversion_exception.go b/java_exception/lambda_conversion_exception.go
index c2ba972..b63e27e 100644
--- a/java_exception/lambda_conversion_exception.go
+++ b/java_exception/lambda_conversion_exception.go
@@ -47,4 +47,4 @@ func (LambdaConversionException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e LambdaConversionException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/malformed_parameterized_type_exception.go b/java_exception/malformed_parameterized_type_exception.go
index 5747ea3..6b8aa3d 100644
--- a/java_exception/malformed_parameterized_type_exception.go
+++ b/java_exception/malformed_parameterized_type_exception.go
@@ -44,4 +44,4 @@ func NewMalformedParameterizedTypeException(detailMessage string) *MalformedPara
 // equals to getStackTrace in java
 func (e MalformedParameterizedTypeException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/malformed_parameters_exception.go b/java_exception/malformed_parameters_exception.go
index 9d2c0f4..1b3a35d 100644
--- a/java_exception/malformed_parameters_exception.go
+++ b/java_exception/malformed_parameters_exception.go
@@ -44,4 +44,4 @@ func NewMalformedParametersException(detailMessage string) *MalformedParametersE
 // equals to getStackTrace in java
 func (e MalformedParametersException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/missing_format_argument_exception.go b/java_exception/missing_format_argument_exception.go
index 791e4d6..b90968d 100644
--- a/java_exception/missing_format_argument_exception.go
+++ b/java_exception/missing_format_argument_exception.go
@@ -47,4 +47,4 @@ func (MissingFormatArgumentException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e MissingFormatArgumentException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/missing_format_width_exception.go b/java_exception/missing_format_width_exception.go
index 52825f5..2f3e87c 100644
--- a/java_exception/missing_format_width_exception.go
+++ b/java_exception/missing_format_width_exception.go
@@ -45,4 +45,4 @@ func (MissingFormatWidthException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e MissingFormatWidthException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/missing_resource_exception.go b/java_exception/missing_resource_exception.go
index 7845aab..604d1ef 100644
--- a/java_exception/missing_resource_exception.go
+++ b/java_exception/missing_resource_exception.go
@@ -46,4 +46,4 @@ func NewMissingResourceException(detailMessage, classname, key string) *MissingR
 // equals to getStackTrace in java
 func (e MissingResourceException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/negative_array_size_exception.go b/java_exception/negative_array_size_exception.go
index e6740a3..538a5d6 100644
--- a/java_exception/negative_array_size_exception.go
+++ b/java_exception/negative_array_size_exception.go
@@ -44,4 +44,4 @@ func (NegativeArraySizeException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e NegativeArraySizeException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/no_such_element_exception.go b/java_exception/no_such_element_exception.go
index a6bb56a..dc56b74 100644
--- a/java_exception/no_such_element_exception.go
+++ b/java_exception/no_such_element_exception.go
@@ -44,4 +44,4 @@ func NewNoSuchElementException(detailMessage string) *NoSuchElementException {
 // equals to getStackTrace in java
 func (e NoSuchElementException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/no_such_field_exception.go b/java_exception/no_such_field_exception.go
index ec06e52..ba292f1 100644
--- a/java_exception/no_such_field_exception.go
+++ b/java_exception/no_such_field_exception.go
@@ -44,4 +44,4 @@ func (NoSuchFieldException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e NoSuchFieldException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/no_such_method_exception.go b/java_exception/no_such_method_exception.go
index 9e0f79b..a34b57d 100644
--- a/java_exception/no_such_method_exception.go
+++ b/java_exception/no_such_method_exception.go
@@ -44,4 +44,4 @@ func (NoSuchMethodException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e NoSuchMethodException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/not_active_exception.go b/java_exception/not_active_exception.go
index 46077c8..48141d3 100644
--- a/java_exception/not_active_exception.go
+++ b/java_exception/not_active_exception.go
@@ -44,4 +44,4 @@ func (NotActiveException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e NotActiveException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/not_serializable_exception.go b/java_exception/not_serializable_exception.go
index ab6dac4..e77c84a 100644
--- a/java_exception/not_serializable_exception.go
+++ b/java_exception/not_serializable_exception.go
@@ -44,4 +44,4 @@ func (NotSerializableException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e NotSerializableException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/null_pointer_exception.go b/java_exception/null_pointer_exception.go
index b1eb851..1686820 100644
--- a/java_exception/null_pointer_exception.go
+++ b/java_exception/null_pointer_exception.go
@@ -44,4 +44,4 @@ func (e NullPointerException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e NullPointerException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/number_format_exception.go b/java_exception/number_format_exception.go
index e7a8008..36c4401 100644
--- a/java_exception/number_format_exception.go
+++ b/java_exception/number_format_exception.go
@@ -44,4 +44,4 @@ func (NumberFormatException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e NumberFormatException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/object_stream_exception.go b/java_exception/object_stream_exception.go
index 3b569d7..eaa0eb8 100644
--- a/java_exception/object_stream_exception.go
+++ b/java_exception/object_stream_exception.go
@@ -44,4 +44,4 @@ func (ObjectStreamException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e ObjectStreamException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/optional_data_exception.go b/java_exception/optional_data_exception.go
index c901bf1..bc1424b 100644
--- a/java_exception/optional_data_exception.go
+++ b/java_exception/optional_data_exception.go
@@ -46,4 +46,4 @@ func (OptionalDataException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e OptionalDataException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/reflective_operation_exception.go b/java_exception/reflective_operation_exception.go
index 703cc65..2db3fc2 100644
--- a/java_exception/reflective_operation_exception.go
+++ b/java_exception/reflective_operation_exception.go
@@ -44,4 +44,4 @@ func (ReflectiveOperationException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e ReflectiveOperationException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/rejected_execution_exception.go b/java_exception/rejected_execution_exception.go
index 1a760c8..940f676 100644
--- a/java_exception/rejected_execution_exception.go
+++ b/java_exception/rejected_execution_exception.go
@@ -44,4 +44,4 @@ func NewRejectedExecutionException(detailMessage string) *RejectedExecutionExcep
 // equals to getStackTrace in java
 func (e RejectedExecutionException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/runtime_exception.go b/java_exception/runtime_exception.go
index d4829c1..5a8dff2 100644
--- a/java_exception/runtime_exception.go
+++ b/java_exception/runtime_exception.go
@@ -44,4 +44,4 @@ func (RuntimeException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e RuntimeException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/security_exception.go b/java_exception/security_exception.go
index fb1961d..f06c741 100644
--- a/java_exception/security_exception.go
+++ b/java_exception/security_exception.go
@@ -44,4 +44,4 @@ func (SecurityException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e SecurityException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/stream_corrupted_exception.go b/java_exception/stream_corrupted_exception.go
index 99793a9..bf27914 100644
--- a/java_exception/stream_corrupted_exception.go
+++ b/java_exception/stream_corrupted_exception.go
@@ -44,4 +44,4 @@ func (StreamCorruptedException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e StreamCorruptedException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/string_index_out_of_bounds_exception.go b/java_exception/string_index_out_of_bounds_exception.go
index 2cce9cd..3dd0495 100644
--- a/java_exception/string_index_out_of_bounds_exception.go
+++ b/java_exception/string_index_out_of_bounds_exception.go
@@ -44,4 +44,4 @@ func (StringIndexOutOfBoundsException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e StringIndexOutOfBoundsException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/sync_failed_exception.go b/java_exception/sync_failed_exception.go
index ba4e7db..e68103b 100644
--- a/java_exception/sync_failed_exception.go
+++ b/java_exception/sync_failed_exception.go
@@ -44,4 +44,4 @@ func (SyncFailedException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e SyncFailedException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/timeout_exception.go b/java_exception/timeout_exception.go
index 8456fda..831b108 100644
--- a/java_exception/timeout_exception.go
+++ b/java_exception/timeout_exception.go
@@ -44,4 +44,4 @@ func (TimeoutException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e TimeoutException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/too_many_listeners_exception.go b/java_exception/too_many_listeners_exception.go
index 68d45b4..16c7f62 100644
--- a/java_exception/too_many_listeners_exception.go
+++ b/java_exception/too_many_listeners_exception.go
@@ -44,4 +44,4 @@ func (TooManyListenersException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e TooManyListenersException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/type_not_present_exception.go b/java_exception/type_not_present_exception.go
index ed15498..9700352 100644
--- a/java_exception/type_not_present_exception.go
+++ b/java_exception/type_not_present_exception.go
@@ -45,4 +45,4 @@ func NewTypeNotPresentException(typeName string, detailMessage string) *TypeNotP
 // equals to getStackTrace in java
 func (e TypeNotPresentException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/unchecked_IO_exception.go b/java_exception/unchecked_IO_exception.go
index ac66e32..c7a8c3b 100644
--- a/java_exception/unchecked_IO_exception.go
+++ b/java_exception/unchecked_IO_exception.go
@@ -48,4 +48,4 @@ func (UncheckedIOException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e UncheckedIOException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/undeclared_throwable_exception.go b/java_exception/undeclared_throwable_exception.go
index 297425d..1483c8a 100644
--- a/java_exception/undeclared_throwable_exception.go
+++ b/java_exception/undeclared_throwable_exception.go
@@ -45,4 +45,4 @@ func NewUndeclaredThrowableException(detailMessage string) *UndeclaredThrowableE
 // equals to getStackTrace in java
 func (e UndeclaredThrowableException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/unknown_format_conversion_exception.go b/java_exception/unknown_format_conversion_exception.go
index 74687af..5b1fb26 100644
--- a/java_exception/unknown_format_conversion_exception.go
+++ b/java_exception/unknown_format_conversion_exception.go
@@ -47,4 +47,4 @@ func (UnknownFormatConversionException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e UnknownFormatConversionException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/unknown_format_flags_exception.go b/java_exception/unknown_format_flags_exception.go
index ae0a334..63da093 100644
--- a/java_exception/unknown_format_flags_exception.go
+++ b/java_exception/unknown_format_flags_exception.go
@@ -45,4 +45,4 @@ func (UnknownFormatFlagsException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e UnknownFormatFlagsException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/unmodifiable_class_exception.go b/java_exception/unmodifiable_class_exception.go
index 4ac7c3d..12755db 100644
--- a/java_exception/unmodifiable_class_exception.go
+++ b/java_exception/unmodifiable_class_exception.go
@@ -47,4 +47,4 @@ func (UnmodifiableClassException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e UnmodifiableClassException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/unsupported_operation_exception.go b/java_exception/unsupported_operation_exception.go
index 3c16ed0..d629eaf 100644
--- a/java_exception/unsupported_operation_exception.go
+++ b/java_exception/unsupported_operation_exception.go
@@ -44,4 +44,4 @@ func (UnsupportedOperationException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e UnsupportedOperationException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/unsupported_temporal_type_exception.go b/java_exception/unsupported_temporal_type_exception.go
index 6ec8f44..91bc184 100644
--- a/java_exception/unsupported_temporal_type_exception.go
+++ b/java_exception/unsupported_temporal_type_exception.go
@@ -44,4 +44,4 @@ func (UnsupportedTemporalTypeException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e UnsupportedTemporalTypeException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/utf_data_format_exception.go b/java_exception/utf_data_format_exception.go
index 356033a..8c6d22f 100644
--- a/java_exception/utf_data_format_exception.go
+++ b/java_exception/utf_data_format_exception.go
@@ -44,4 +44,4 @@ func (UTFDataFormatException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e UTFDataFormatException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/write_aborted_exception.go b/java_exception/write_aborted_exception.go
index 7f24bdb..bbaa1e2 100644
--- a/java_exception/write_aborted_exception.go
+++ b/java_exception/write_aborted_exception.go
@@ -46,4 +46,4 @@ func (WriteAbortedException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e WriteAbortedException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/wrong_method_type_exception.go b/java_exception/wrong_method_type_exception.go
index 2fd20c7..a0fcb0f 100644
--- a/java_exception/wrong_method_type_exception.go
+++ b/java_exception/wrong_method_type_exception.go
@@ -44,4 +44,4 @@ func NewWrongMethodTypeException(detailMessage string) *WrongMethodTypeException
 // equals to getStackTrace in java
 func (e WrongMethodTypeException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/zip_exception.go b/java_exception/zip_exception.go
index 894134d..9a92704 100644
--- a/java_exception/zip_exception.go
+++ b/java_exception/zip_exception.go
@@ -44,4 +44,4 @@ func (ZipException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e ZipException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_exception/zone_rules_exception.go b/java_exception/zone_rules_exception.go
index 4143ae4..871dba3 100644
--- a/java_exception/zone_rules_exception.go
+++ b/java_exception/zone_rules_exception.go
@@ -44,4 +44,4 @@ func (ZoneRulesException) JavaClassName() string {
 // equals to getStackTrace in java
 func (e ZoneRulesException) GetStackTrace() []StackTraceElement {
 	return e.StackTrace
-}
\ No newline at end of file
+}
diff --git a/java_unknown_exception.go b/java_unknown_exception.go
index 6787e3c..1b4196c 100644
--- a/java_unknown_exception.go
+++ b/java_unknown_exception.go
@@ -26,7 +26,7 @@ import (
 	"github.com/apache/dubbo-go-hessian2/java_exception"
 )
 
-var mutex sync.Mutex
+var exceptionCheckMutex sync.Mutex
 
 func checkAndGetException(cls classInfo) (structInfo, bool) {
 
@@ -45,8 +45,8 @@ func checkAndGetException(cls classInfo) (structInfo, bool) {
 	}
 	// if have these 4 fields, it is throwable struct
 	if count == 4 {
-		mutex.Lock()
-		defer mutex.Unlock()
+		exceptionCheckMutex.Lock()
+		defer exceptionCheckMutex.Unlock()
 		if throwable, ok = getStructInfo(cls.javaName); ok {
 			return throwable, true
 		}
diff --git a/list.go b/list.go
index 87aef90..0eed874 100644
--- a/list.go
+++ b/list.go
@@ -284,6 +284,8 @@ func (d *Decoder) decList(flag int32) (interface{}, error) {
 		return d.readTypedList(tag)
 	case untypedListTag(tag):
 		return d.readUntypedList(tag)
+	case binaryTag(tag):
+		return d.decBinary(int32(tag))
 	default:
 		return nil, perrors.Errorf("error list tag: 0x%x", tag)
 	}
diff --git a/output/output.go b/output/output.go
new file mode 100644
index 0000000..2e13a5b
--- /dev/null
+++ b/output/output.go
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"os"
+)
+
+import (
+	"github.com/apache/dubbo-go-hessian2/output/testfuncs"
+)
+
+type outputFunc func() []byte
+
+var (
+	funcName = flag.String("func_name", "", "func name")
+	funcMap  = make(map[string]outputFunc, 8)
+)
+
+// add all output func here
+func init() {
+	funcMap["HelloWorldString"] = testfuncs.HelloWorldString
+}
+
+func main() {
+	flag.Parse()
+
+	if *funcName == "" {
+		_, _ = fmt.Fprintln(os.Stderr, "func name required")
+		os.Exit(1)
+	}
+	f, exist := funcMap[*funcName]
+	if !exist {
+		_, _ = fmt.Fprintln(os.Stderr, "func name not exist: ", *funcName)
+		os.Exit(1)
+	}
+
+	defer func() {
+		if err := recover(); err != nil {
+			_, _ = fmt.Fprintln(os.Stderr, "error: ", err)
+			os.Exit(1)
+		}
+	}()
+	if _, err := os.Stdout.Write(f()); err != nil {
+		_, _ = fmt.Fprintln(os.Stderr, "call error: ", err)
+		os.Exit(1)
+	}
+	os.Exit(0)
+}


Test patch:
diff --git a/decode_test.go b/decode_test.go
index 30468d7..87f4604 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -24,12 +24,18 @@
 package hessian
 
 import (
+	"fmt"
 	"log"
 	"os"
 	"os/exec"
 	"reflect"
 	"testing"
 )
+
+import (
+	"github.com/stretchr/testify/assert"
+)
+
 import (
 	"github.com/apache/dubbo-go-hessian2/java_exception"
 )
@@ -145,3 +151,42 @@ func TestUserDefindeException(t *testing.T) {
 	}
 	testDecodeFramework(t, "throw_UserDefindException", expect)
 }
+
+type Circular214 struct {
+	Num      int
+	Previous *Circular214
+	Next     *Circular214
+	Bytes    []byte
+}
+
+func (Circular214) JavaClassName() string {
+	return "com.company.Circular"
+}
+
+func (c *Circular214) String() string {
+	return fmt.Sprintf("Addr:%p, Num: %d, Previous: %p, Next: %p, Bytes: %s", c, c.Num, c.Previous, c.Next, c.Bytes)
+}
+
+func TestIssue214(t *testing.T) {
+	c := &Circular214{}
+	c.Num = 1234
+	c.Previous = c
+	c.Next = c
+	c.Bytes = []byte(`{"a":"b"}`)
+	e := NewEncoder()
+	err := e.Encode(c)
+	if err != nil {
+		assert.FailNow(t, fmt.Sprintf("%v", err))
+		return
+	}
+
+	bytes := e.Buffer()
+	decoder := NewDecoder(bytes)
+	decode, err := decoder.Decode()
+	if err != nil {
+		assert.FailNow(t, fmt.Sprintf("%v", err))
+		return
+	}
+	t.Log(decode)
+	assert.True(t, reflect.DeepEqual(c, decode))
+}
diff --git a/java8_time_test.go b/java8_time_test.go
new file mode 100644
index 0000000..7506291
--- /dev/null
+++ b/java8_time_test.go
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package hessian
+
+import (
+	"github.com/apache/dubbo-go-hessian2/java8_time"
+	"testing"
+)
+
+func TestJava8Time(t *testing.T) {
+	doTestTime(t, "java8_Year", &java8_time.Year{Year: 2020})
+	doTestTime(t, "java8_LocalDate", &java8_time.LocalDate{Year: 2020, Month: 6, Day: 6})
+	doTestTime(t, "java8_LocalTime", &java8_time.LocalTime{Hour: 6, Minute: 6})
+	doTestTime(t, "java8_LocalDateTime", &java8_time.LocalDateTime{Date: java8_time.LocalDate{Year: 2020, Month: 6, Day: 6}, Time: java8_time.LocalTime{Hour: 6, Minute: 6}})
+	doTestTime(t, "java8_MonthDay", &java8_time.MonthDay{Month: 6, Day: 6})
+	doTestTime(t, "java8_Duration", &java8_time.Duration{Second: 0, Nano: 0})
+	doTestTime(t, "java8_Instant", &java8_time.Instant{Seconds: 100, Nanos: 0})
+	doTestTime(t, "java8_YearMonth", &java8_time.YearMonth{Year: 2020, Month: 6})
+	doTestTime(t, "java8_Period", &java8_time.Period{Years: 2020, Months: 6, Days: 6})
+}
+
+func doTestTime(t *testing.T, method string, expected interface{}) {
+	testDecodeFramework(t, method, expected)
+}
diff --git a/output/testfuncs/string.go b/output/testfuncs/string.go
new file mode 100644
index 0000000..9e3eda7
--- /dev/null
+++ b/output/testfuncs/string.go
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package testfuncs
+
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+)
+
+func HelloWorldString() []byte {
+	e := hessian.NewEncoder()
+	e.Encode("hello world")
+	return e.Buffer()
+}
diff --git a/test_hessian/pom.xml b/test_hessian/pom.xml
index 6146e38..acd9188 100644
--- a/test_hessian/pom.xml
+++ b/test_hessian/pom.xml
@@ -47,6 +47,12 @@
             <artifactId>dubbo</artifactId>
             <version>2.6.5</version>
         </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.13</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/test_hessian/src/main/java/test/Hessian.java b/test_hessian/src/main/java/test/Hessian.java
index b954541..f26cbed 100644
--- a/test_hessian/src/main/java/test/Hessian.java
+++ b/test_hessian/src/main/java/test/Hessian.java
@@ -59,6 +59,15 @@ public class Hessian {
             TestHessian2Servlet servlet = new TestHessian2Servlet();
             Object object = method.invoke(servlet);
 
+            Hessian2Output output = new Hessian2Output(System.out);
+            output.writeObject(object);
+            output.flush();
+        }else if(args[0].startsWith("java8_")){
+            //add java8 java.time Object test
+            Method method = TestJava8Time.class.getMethod(args[0]);
+            Object obj = new Object();
+            Object object =method.invoke(obj);
+
             Hessian2Output output = new Hessian2Output(System.out);
             output.writeObject(object);
             output.flush();
diff --git a/test_hessian/src/main/java/test/TestJava8Time.java b/test_hessian/src/main/java/test/TestJava8Time.java
new file mode 100644
index 0000000..a4e39f0
--- /dev/null
+++ b/test_hessian/src/main/java/test/TestJava8Time.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package test;
+
+import java.time.*;
+
+public class TestJava8Time {
+
+    public static Duration java8_Duration() {
+        return Duration.ZERO;
+    }
+
+    public static Instant java8_Instant() {
+        return Instant.ofEpochMilli(100000L);
+    }
+
+    public static LocalDate java8_LocalDate() {
+        return LocalDate.of(2020, 6, 6);
+    }
+
+    public static LocalDateTime java8_LocalDateTime() {
+        return LocalDateTime.of(2020, 6, 6, 6, 6);
+    }
+
+    public static LocalTime java8_LocalTime() {
+        return LocalTime.of(6, 6);
+    }
+
+    public static MonthDay java8_MonthDay() {
+        return MonthDay.of(6, 6);
+    }
+
+    public static OffsetDateTime java8_OffsetDateTime() {
+        return OffsetDateTime.of(2020, 6, 6, 6, 6, 6, 6, ZoneOffset.MIN);
+    }
+
+    public static OffsetTime java8_OffsetTime() {
+        return OffsetTime.of(6, 6, 6, 6, ZoneOffset.MIN);
+    }
+
+    public static Period java8_Period() {
+        return Period.of(2020, 6, 6);
+    }
+
+    public static Year java8_Year() {
+        return Year.of(2020);
+    }
+
+    public static YearMonth java8_YearMonth() {
+        return YearMonth.of(2020, 6);
+    }
+
+    public static ZonedDateTime java8_ZonedDateTime() {
+        ZonedDateTime of = ZonedDateTime.of(java8_LocalDateTime(), java8_ZoneId());
+        return of;
+    }
+
+    public static ZoneId java8_ZoneId() {
+        return ZoneId.of("1000");
+    }
+
+    public static ZoneOffset java8_ZoneOffset() {
+        return ZoneOffset.of("1000");
+    }
+
+}
diff --git a/test_hessian/src/test/java/unit/GoStringTest.java b/test_hessian/src/test/java/unit/GoStringTest.java
new file mode 100644
index 0000000..fe2c27f
--- /dev/null
+++ b/test_hessian/src/test/java/unit/GoStringTest.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package unit;
+
+
+import junit.framework.Assert;
+import org.junit.Test;
+
+/**
+ * @author wongoo
+ */
+public class GoStringTest {
+
+    @Test
+    public void testHelloWordString() {
+        Assert.assertEquals("hello world"
+                , GoTestUtil.readGoObject("HelloWorldString"));
+    }
+}
diff --git a/test_hessian/src/test/java/unit/GoTestUtil.java b/test_hessian/src/test/java/unit/GoTestUtil.java
new file mode 100644
index 0000000..5b776f6
--- /dev/null
+++ b/test_hessian/src/test/java/unit/GoTestUtil.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package unit;
+
+import com.alibaba.com.caucho.hessian.io.Hessian2Input;
+import junit.framework.Assert;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @author wongoo
+ */
+public class GoTestUtil {
+
+    public static Object readGoObject(String func) {
+        System.out.println("read go data: " + func);
+        try {
+            Process process = Runtime.getRuntime()
+                    .exec("go run output/output.go -func_name=" + func,
+                            null,
+                            new File(".."));
+
+            int exitValue = process.waitFor();
+            if (exitValue != 0) {
+                Assert.fail(readString(process.getErrorStream()));
+                return null;
+            }
+
+            InputStream is = process.getInputStream();
+            Hessian2Input input = new Hessian2Input(is);
+            return input.readObject();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    private static String readString(InputStream in) throws IOException {
+        StringBuilder out = new StringBuilder();
+        InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
+        char[] buffer = new char[4096];
+
+        int bytesRead;
+        while ((bytesRead = reader.read(buffer)) != -1) {
+            out.append(buffer, 0, bytesRead);
+        }
+
+        return out.toString();
+    }
+}