Repository: apache/dubbo-go-hessian2
Pull request #227 (2020-09-06 08:38:11)

Release merge for v1.7.0 (based on v1.6.0)

**What this PR does**:
Release merge for v1.7.0 (based on v1.6.0)

**release-note**:
### New Features
- add GetStackTrace method into Throwabler and its implements. [#207](https://github.com/apache/dubbo-go-hessian2/pull/207)
- catch user defined exceptions. [#208](https://github.com/apache/dubbo-go-hessian2/pull/208)
- support java8 time object. [#212](https://github.com/apache/dubbo-go-hessian2/pull/212), [#221](https://github.com/apache/dubbo-go-hessian2/pull/221)
- support test golang encoding data in java. [#213](https://github.com/apache/dubbo-go-hessian2/pull/213)
- support java.sql.Time & java.sql.Date. [#219](https://github.com/apache/dubbo-go-hessian2/pull/219)

### Enhancement
- Export function EncNull. [#225](https://github.com/apache/dubbo-go-hessian2/pull/225)

### Bugfixes
- fix eunm encode error in request. [#203](https://github.com/apache/dubbo-go-hessian2/pull/203)
- fix []byte field decoding issue. [#216](https://github.com/apache/dubbo-go-hessian2/pull/216)




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/CHANGE.md b/CHANGE.md
index 492220c..2690398 100644
--- a/CHANGE.md
+++ b/CHANGE.md
@@ -1,5 +1,22 @@
 # Release Notes
 
+## v1.7.0
+
+### New Features
+- add GetStackTrace method into Throwabler and its implements. [#207](https://github.com/apache/dubbo-go-hessian2/pull/207)
+- catch user defined exceptions. [#208](https://github.com/apache/dubbo-go-hessian2/pull/208)
+- support java8 time object. [#212](https://github.com/apache/dubbo-go-hessian2/pull/212), [#221](https://github.com/apache/dubbo-go-hessian2/pull/221)
+- support test golang encoding data in java. [#213](https://github.com/apache/dubbo-go-hessian2/pull/213)
+- support java.sql.Time & java.sql.Date. [#219](https://github.com/apache/dubbo-go-hessian2/pull/219)
+
+### Enhancement
+- Export function EncNull. [#225](https://github.com/apache/dubbo-go-hessian2/pull/225)
+
+### Bugfixes
+- fix eunm encode error in request. [#203](https://github.com/apache/dubbo-go-hessian2/pull/203)
+- fix []byte field decoding issue. [#216](https://github.com/apache/dubbo-go-hessian2/pull/216)
+- fix decoding error for map in map. [#229](https://github.com/apache/dubbo-go-hessian2/pull/229)
+
 ## v1.6.0
 
 ### New Features
diff --git a/README.md b/README.md
index 6bc9b78..2887670 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,8 @@ thanks to [micln](https://github.com/micln), [pantianying](https://github.com/pa
 * [Field Alias By Alias](https://github.com/apache/dubbo-go-hessian2/issues/19)
 * [Java Bigdecimal](https://github.com/apache/dubbo-go-hessian2/issues/89)
 * [Java Date & Time](https://github.com/apache/dubbo-go-hessian2/issues/90)
+* [java8 time.Date](https://github.com/apache/dubbo-go-hessian2/pull/212)
+* [java8 java.sql.Time & java.sql.Date](https://github.com/apache/dubbo-go-hessian2/pull/219)
 * [Java Generic Invokation](https://github.com/apache/dubbo-go-hessian2/issues/84)
 * [Java Extends](https://github.com/apache/dubbo-go-hessian2/issues/157)
 * [Dubbo Attachements](https://github.com/apache/dubbo-go-hessian2/issues/49)
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/contributing.md b/contributing.md
index 15c9610..ec5b83f 100644
--- a/contributing.md
+++ b/contributing.md
@@ -1,4 +1,4 @@
-Contributing to Hessian2 Protocol Go Implementation
+Contributing to Dubbo-go-hessian2
 
 ## 1. Branch
 
@@ -24,3 +24,41 @@ The title format of the pull request `MUST` follow the following rules:
   >- Start with `Dep:` for adding depending libs.
   >- Start with `Rem:` for removing feature/struct/function/member/files.
 
+## 3. Code Style
+
+### 3.1 log
+
+>- 1 when logging the function's input parameter, you should add '@' before input parameter name.
+
+### 3.2 naming
+
+>- 1 do not use an underscore in package name, such as `filter_impl`.
+>- 2 do not use an underscore in constants, such as `DUBBO_PROTOCOL`. use 'DubboProtocol' instead.
+
+### 3.3 comment
+
+>- 1 there should be comment for every export func/var.
+>- 2 the comment should begin with function name/var name.
+
+### 3.4 import
+
+We dubbogo import blocks should be splited into 3 blocks.
+
+```Go
+// block 1: the go internal package
+import (
+  "fmt"
+)
+
+// block 2: the third package
+import (
+  "github.com/dubbogo/xxx"
+
+  "github.com/RoaringBitmap/roaring"
+)
+
+// block 3: the dubbo-go package
+import (
+  "github.com/apache/dubbo-go/common"
+)
+```
diff --git a/encode.go b/encode.go
index ad9d5c6..2ae6791 100644
--- a/encode.go
+++ b/encode.go
@@ -61,13 +61,13 @@ func (e *Encoder) Append(buf []byte) {
 // Encode If @v can not be encoded, the return value is nil. At present only struct may can not be encoded.
 func (e *Encoder) Encode(v interface{}) error {
 	if v == nil {
-		e.buffer = encNull(e.buffer)
+		e.buffer = EncNull(e.buffer)
 		return nil
 	}
 
 	switch val := v.(type) {
 	case nil:
-		e.buffer = encNull(e.buffer)
+		e.buffer = EncNull(e.buffer)
 		return nil
 
 	case bool:
@@ -105,7 +105,7 @@ func (e *Encoder) Encode(v interface{}) error {
 
 	case time.Time:
 		if ZeroDate == val {
-			e.buffer = encNull(e.buffer)
+			e.buffer = EncNull(e.buffer)
 		} else {
 			e.buffer = encDateInMs(e.buffer, &val)
 			// e.buffer = encDateInMimute(v.(time.Time), e.buffer)
@@ -138,7 +138,7 @@ func (e *Encoder) Encode(v interface{}) error {
 			vv := reflect.ValueOf(v)
 			vv = UnpackPtr(vv)
 			if !vv.IsValid() {
-				e.buffer = encNull(e.buffer)
+				e.buffer = EncNull(e.buffer)
 				return nil
 			}
 			if vv.Type().String() == "time.Time" {
diff --git a/int.go b/int.go
index 5263a3f..0581170 100644
--- a/int.go
+++ b/int.go
@@ -110,7 +110,7 @@ func (d *Decoder) decInt32(flag int32) (int32, error) {
 func (d *Encoder) encTypeInt32(b []byte, p interface{}) ([]byte, error) {
 	value := reflect.ValueOf(p)
 	if PackPtr(value).IsNil() {
-		return encNull(b), nil
+		return EncNull(b), nil
 	}
 	value = UnpackPtrValue(value)
 	if value.Kind() != reflect.Int32 {
diff --git a/java8_time.go b/java8_time.go
new file mode 100644
index 0000000..6d5283f
--- /dev/null
+++ b/java8_time.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"
+)
+
+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, Second: 6, Nano: 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})
+	RegisterPOJO(&java8_time.ZoneOffSet{Seconds: 0})
+	RegisterPOJO(&java8_time.OffsetDateTime{DateTime: java8_time.LocalDateTime{Date: java8_time.LocalDate{Year: 2020, Month: 6, Day: 6}, Time: java8_time.LocalTime{Hour: 6, Minute: 6, Second: 6, Nano: 6}}, Offset: java8_time.ZoneOffSet{Seconds: -64800}})
+	RegisterPOJO(&java8_time.OffsetTime{LocalTime: java8_time.LocalTime{Hour: 6, Minute: 6, Second: 6, Nano: 6}, ZoneOffset: java8_time.ZoneOffSet{Seconds: -64800}})
+	RegisterPOJO(&java8_time.ZonedDateTime{DateTime: java8_time.LocalDateTime{Date: java8_time.LocalDate{Year: 2020, Month: 6, Day: 6}, Time: java8_time.LocalTime{Hour: 6, Minute: 6, Second: 6, Nano: 6}}, Offset: java8_time.ZoneOffSet{Seconds: 0}, ZoneId: "Z"})
+
+}
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/offset_date_time.go b/java8_time/offset_date_time.go
new file mode 100644
index 0000000..986a804
--- /dev/null
+++ b/java8_time/offset_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 OffsetDateTime struct {
+	DateTime LocalDateTime `hessian:"dateTime"`
+	Offset   ZoneOffSet    `hessian:"offset"`
+}
+
+func (OffsetDateTime) JavaClassName() string {
+	return "com.alibaba.com.caucho.hessian.io.java8.OffsetDateTimeHandle"
+}
+
+func (OffsetDateTime) Error() string {
+	return "encode OffsetDateTime error"
+}
diff --git a/java8_time/offset_time.go b/java8_time/offset_time.go
new file mode 100644
index 0000000..9adc215
--- /dev/null
+++ b/java8_time/offset_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 OffsetTime struct {
+	LocalTime  LocalTime  `hessian:"localTime"`
+	ZoneOffset ZoneOffSet `hessian:"zoneOffset"`
+}
+
+func (OffsetTime) JavaClassName() string {
+	return "com.alibaba.com.caucho.hessian.io.java8.OffsetTimeHandle"
+}
+
+func (OffsetTime) Error() string {
+	return "encode OffsetDateTime 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/java8_time/zone_off_set.go b/java8_time/zone_off_set.go
new file mode 100644
index 0000000..9b2e8a9
--- /dev/null
+++ b/java8_time/zone_off_set.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
+
+type ZoneOffSet struct {
+	Seconds int32 `hessian:"seconds"`
+}
+
+func (ZoneOffSet) JavaClassName() string {
+	return "com.alibaba.com.caucho.hessian.io.java8.ZoneOffsetHandle"
+}
+
+func (ZoneOffSet) Error() string {
+	return "encode ZoneOffSet error"
+}
diff --git a/java8_time/zoned_date_time.go b/java8_time/zoned_date_time.go
new file mode 100644
index 0000000..2e1eeb2
--- /dev/null
+++ b/java8_time/zoned_date_time.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 ZonedDateTime struct {
+	DateTime LocalDateTime `hessian:"dateTime"`
+	Offset   ZoneOffSet    `hessian:"offset"`
+	ZoneId   string        `hessian:"zoneId"`
+}
+
+func (ZonedDateTime) JavaClassName() string {
+	return "com.alibaba.com.caucho.hessian.io.java8.ZonedDateTimeHandle"
+}
+
+func (ZonedDateTime) Error() string {
+	return "encode ZonedDateTime error"
+}
diff --git a/java_exception/annotation_type_mismatch_exception.go b/java_exception/annotation_type_mismatch_exception.go
index c0e482d..a3e702c 100644
--- a/java_exception/annotation_type_mismatch_exception.go
+++ b/java_exception/annotation_type_mismatch_exception.go
@@ -42,3 +42,8 @@ func (e AnnotationTypeMismatchException) Error() string {
 func (AnnotationTypeMismatchException) JavaClassName() string {
 	return "java.lang.annotation.AnnotationTypeMismatchException"
 }
+
+// equals to getStackTrace in java
+func (e AnnotationTypeMismatchException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/arithmetic_exception.go b/java_exception/arithmetic_exception.go
index 8af4640..c9b7e1d 100644
--- a/java_exception/arithmetic_exception.go
+++ b/java_exception/arithmetic_exception.go
@@ -40,3 +40,8 @@ func (e ArithmeticException) Error() string {
 func (ArithmeticException) JavaClassName() string {
 	return "java.lang.ArithmeticException"
 }
+
+// equals to getStackTrace in java
+func (e ArithmeticException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/array_index_out_of_bounds_exception.go b/java_exception/array_index_out_of_bounds_exception.go
index ef85247..6555cd4 100644
--- a/java_exception/array_index_out_of_bounds_exception.go
+++ b/java_exception/array_index_out_of_bounds_exception.go
@@ -40,3 +40,8 @@ func (e ArrayIndexOutOfBoundsException) Error() string {
 func (ArrayIndexOutOfBoundsException) JavaClassName() string {
 	return "java.lang.ArrayIndexOutOfBoundsException"
 }
+
+// equals to getStackTrace in java
+func (e ArrayIndexOutOfBoundsException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/array_store_exception.go b/java_exception/array_store_exception.go
index 98a23b9..94bcf52 100644
--- a/java_exception/array_store_exception.go
+++ b/java_exception/array_store_exception.go
@@ -40,3 +40,8 @@ func (e ArrayStoreException) Error() string {
 func (ArrayStoreException) JavaClassName() string {
 	return "java.lang.ArrayStoreException"
 }
+
+// equals to getStackTrace in java
+func (e ArrayStoreException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/backing_store_exception.go b/java_exception/backing_store_exception.go
index 8224aaa..72d5ade 100644
--- a/java_exception/backing_store_exception.go
+++ b/java_exception/backing_store_exception.go
@@ -40,3 +40,8 @@ func (e BackingStoreException) Error() string {
 func (BackingStoreException) JavaClassName() string {
 	return "java.util.prefs.BackingStoreException"
 }
+
+// equals to getStackTrace in java
+func (e BackingStoreException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/broken_barrier_exception.go b/java_exception/broken_barrier_exception.go
index 47fbc0e..c018432 100644
--- a/java_exception/broken_barrier_exception.go
+++ b/java_exception/broken_barrier_exception.go
@@ -40,3 +40,8 @@ func (e BrokenBarrierException) Error() string {
 func (BrokenBarrierException) JavaClassName() string {
 	return "java.util.concurrent.BrokenBarrierException"
 }
+
+// equals to getStackTrace in java
+func (e BrokenBarrierException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/cancellation_exception.go b/java_exception/cancellation_exception.go
index facaa70..be7be99 100644
--- a/java_exception/cancellation_exception.go
+++ b/java_exception/cancellation_exception.go
@@ -40,3 +40,8 @@ func (e CancellationException) Error() string {
 func (CancellationException) JavaClassName() string {
 	return "java.util.concurrent.CancellationException"
 }
+
+// equals to getStackTrace in java
+func (e CancellationException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/class_not_found_exception.go b/java_exception/class_not_found_exception.go
index b987e74..1963256 100644
--- a/java_exception/class_not_found_exception.go
+++ b/java_exception/class_not_found_exception.go
@@ -41,3 +41,8 @@ func (e ClassNotFoundException) Error() string {
 func (ClassNotFoundException) JavaClassName() string {
 	return "java.lang.ClassNotFoundException"
 }
+
+// equals to getStackTrace in java
+func (e ClassNotFoundException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/classc_cast_exception.go b/java_exception/classc_cast_exception.go
index 4d50d18..11fd796 100644
--- a/java_exception/classc_cast_exception.go
+++ b/java_exception/classc_cast_exception.go
@@ -40,3 +40,8 @@ func (e ClassCastException) Error() string {
 func (ClassCastException) JavaClassName() string {
 	return "java.lang.ClassCastException"
 }
+
+// equals to getStackTrace in java
+func (e ClassCastException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/clone_not_supported_exception.go b/java_exception/clone_not_supported_exception.go
index 38bb4ec..ee1abd0 100644
--- a/java_exception/clone_not_supported_exception.go
+++ b/java_exception/clone_not_supported_exception.go
@@ -44,3 +44,8 @@ func (e CloneNotSupportedException) Error() string {
 func (CloneNotSupportedException) JavaClassName() string {
 	return "java.lang.CloneNotSupportedException"
 }
+
+// equals to getStackTrace in java
+func (e CloneNotSupportedException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/completion_exception.go b/java_exception/completion_exception.go
index 43e3d17..7accd5e 100644
--- a/java_exception/completion_exception.go
+++ b/java_exception/completion_exception.go
@@ -40,3 +40,8 @@ func (CompletionException) JavaClassName() string {
 func NewCompletionException(detailMessage string) *CompletionException {
 	return &CompletionException{DetailMessage: detailMessage}
 }
+
+// equals to getStackTrace in java
+func (e CompletionException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/concurrent_modification_exception.go b/java_exception/concurrent_modification_exception.go
index 4f73bb5..4f50854 100644
--- a/java_exception/concurrent_modification_exception.go
+++ b/java_exception/concurrent_modification_exception.go
@@ -40,3 +40,8 @@ func (ConcurrentModificationException) JavaClassName() string {
 func NewConcurrentModificationException(detailMessage string) *ConcurrentModificationException {
 	return &ConcurrentModificationException{DetailMessage: detailMessage}
 }
+
+// equals to getStackTrace in java
+func (e ConcurrentModificationException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/data_format_exception.go b/java_exception/data_format_exception.go
index ce5fed3..e4b0e23 100644
--- a/java_exception/data_format_exception.go
+++ b/java_exception/data_format_exception.go
@@ -40,3 +40,8 @@ func (e DataFormatException) Error() string {
 func (DataFormatException) JavaClassName() string {
 	return "java.util.zip.DataFormatException"
 }
+
+// equals to getStackTrace in java
+func (e DataFormatException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/date_time_exception.go b/java_exception/date_time_exception.go
index 61fb270..6d0f0e8 100644
--- a/java_exception/date_time_exception.go
+++ b/java_exception/date_time_exception.go
@@ -40,3 +40,8 @@ func (e DateTimeException) Error() string {
 func (DateTimeException) JavaClassName() string {
 	return "java.time.DateTimeException"
 }
+
+// equals to getStackTrace in java
+func (e DateTimeException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/date_time_parse_exception.go b/java_exception/date_time_parse_exception.go
index e8cb5d6..4cb7247 100644
--- a/java_exception/date_time_parse_exception.go
+++ b/java_exception/date_time_parse_exception.go
@@ -42,3 +42,8 @@ func (e DateTimeParseException) Error() string {
 func (DateTimeParseException) JavaClassName() string {
 	return "java.time.format.DateTimeParseException"
 }
+
+// equals to getStackTrace in java
+func (e DateTimeParseException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/dubbo_generic_exception.go b/java_exception/dubbo_generic_exception.go
index f3e0e45..4acde47 100644
--- a/java_exception/dubbo_generic_exception.go
+++ b/java_exception/dubbo_generic_exception.go
@@ -42,3 +42,8 @@ func (e DubboGenericException) Error() string {
 func (DubboGenericException) JavaClassName() string {
 	return "com.alibaba.dubbo.rpc.service.GenericException"
 }
+
+// equals to getStackTrace in java
+func (e DubboGenericException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/duplicate_format_flags_exception.go b/java_exception/duplicate_format_flags_exception.go
index d99f477..b3358ae 100644
--- a/java_exception/duplicate_format_flags_exception.go
+++ b/java_exception/duplicate_format_flags_exception.go
@@ -46,3 +46,8 @@ func (DuplicateFormatFlagsException) JavaClassName() string {
 func NewDuplicateFormatFlagsException(detailMessage string) *DuplicateFormatFlagsException {
 	return &DuplicateFormatFlagsException{DetailMessage: detailMessage}
 }
+
+// equals to getStackTrace in java
+func (e DuplicateFormatFlagsException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/empty_stack_exception.go b/java_exception/empty_stack_exception.go
index 91793ab..a2f516c 100644
--- a/java_exception/empty_stack_exception.go
+++ b/java_exception/empty_stack_exception.go
@@ -40,3 +40,8 @@ func (EmptyStackException) JavaClassName() string {
 func NewEmptyStackException(detailMessage string) *EmptyStackException {
 	return &EmptyStackException{DetailMessage: detailMessage}
 }
+
+// equals to getStackTrace in java
+func (e EmptyStackException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/enum_constant_not_present_exception.go b/java_exception/enum_constant_not_present_exception.go
index 1e6c96e..c8a5aa6 100644
--- a/java_exception/enum_constant_not_present_exception.go
+++ b/java_exception/enum_constant_not_present_exception.go
@@ -42,3 +42,8 @@ func (e EnumConstantNotPresentException) Error() string {
 func (EnumConstantNotPresentException) JavaClassName() string {
 	return "java.lang.EnumConstantNotPresentException"
 }
+
+// equals to getStackTrace in java
+func (e EnumConstantNotPresentException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/eof_exception.go b/java_exception/eof_exception.go
index 7e72123..25127f8 100644
--- a/java_exception/eof_exception.go
+++ b/java_exception/eof_exception.go
@@ -40,3 +40,8 @@ func (e EOFException) Error() string {
 func (EOFException) JavaClassName() string {
 	return "java.io.EOFException"
 }
+
+// equals to getStackTrace in java
+func (e EOFException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/exception.go b/java_exception/exception.go
index 19f952a..f5a00e9 100644
--- a/java_exception/exception.go
+++ b/java_exception/exception.go
@@ -25,6 +25,7 @@ package java_exception
 type Throwabler interface {
 	Error() string
 	JavaClassName() string
+	GetStackTrace() []StackTraceElement
 }
 
 ////////////////////////////
@@ -54,6 +55,11 @@ func (Throwable) JavaClassName() string {
 	return "java.lang.Throwable"
 }
 
+// equals to getStackTrace in java
+func (e Throwable) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
+
 ////////////////////////////
 // Exception
 ////////////////////////////
@@ -79,15 +85,20 @@ func (Exception) JavaClassName() string {
 	return "java.lang.Exception"
 }
 
-////////////////////////////
+// equals to getStackTrace in java
+func (e Exception) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
+
+/////////////////////////////
 // StackTraceElement
-////////////////////////////
+/////////////////////////////
 
 type StackTraceElement struct {
 	DeclaringClass string
 	MethodName     string
 	FileName       string
-	LineNumber     int
+	LineNumber     int32
 }
 
 //JavaClassName  java fully qualified path
diff --git a/java_exception/execution_exception.go b/java_exception/execution_exception.go
index ea75cbb..f57789b 100644
--- a/java_exception/execution_exception.go
+++ b/java_exception/execution_exception.go
@@ -40,3 +40,8 @@ func (e ExecutionException) Error() string {
 func (ExecutionException) JavaClassName() string {
 	return "java.util.concurrent.ExecutionException"
 }
+
+// equals to getStackTrace in java
+func (e ExecutionException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/file_not_found_exception.go b/java_exception/file_not_found_exception.go
index 2a09aba..8fcb6ca 100644
--- a/java_exception/file_not_found_exception.go
+++ b/java_exception/file_not_found_exception.go
@@ -40,3 +40,8 @@ func (e FileNotFoundException) Error() string {
 func (FileNotFoundException) JavaClassName() string {
 	return "java.io.FileNotFoundException"
 }
+
+// equals to getStackTrace in java
+func (e FileNotFoundException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/formatter_closed_exception.go b/java_exception/formatter_closed_exception.go
index 61c8277..784339a 100644
--- a/java_exception/formatter_closed_exception.go
+++ b/java_exception/formatter_closed_exception.go
@@ -40,3 +40,8 @@ func (e FormatterClosedException) Error() string {
 func (FormatterClosedException) JavaClassName() string {
 	return "java.util.FormatterClosedException"
 }
+
+// equals to getStackTrace in java
+func (e FormatterClosedException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/illegal_access_exception.go b/java_exception/illegal_access_exception.go
index 06a1d57..47db075 100644
--- a/java_exception/illegal_access_exception.go
+++ b/java_exception/illegal_access_exception.go
@@ -40,3 +40,8 @@ func (e IllegalAccessException) Error() string {
 func (IllegalAccessException) JavaClassName() string {
 	return "java.lang.IllegalAccessException"
 }
+
+// equals to getStackTrace in java
+func (e IllegalAccessException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/illegal_argument_exception.go b/java_exception/illegal_argument_exception.go
index c8db71c..85db37b 100644
--- a/java_exception/illegal_argument_exception.go
+++ b/java_exception/illegal_argument_exception.go
@@ -40,3 +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
+}
diff --git a/java_exception/illegal_classFormat_exception.go b/java_exception/illegal_classFormat_exception.go
index 5411529..acb79b2 100644
--- a/java_exception/illegal_classFormat_exception.go
+++ b/java_exception/illegal_classFormat_exception.go
@@ -40,3 +40,8 @@ func (e IllegalClassFormatException) Error() string {
 func (IllegalClassFormatException) JavaClassName() string {
 	return "java.lang.instrument.IllegalClassFormatException"
 }
+
+// equals to getStackTrace in java
+func (e IllegalClassFormatException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/illegal_format_code_point_exception.go b/java_exception/illegal_format_code_point_exception.go
index 79cdd2f..3efd4d7 100644
--- a/java_exception/illegal_format_code_point_exception.go
+++ b/java_exception/illegal_format_code_point_exception.go
@@ -43,3 +43,8 @@ func (e IllegalFormatCodePointException) Error() string {
 func (IllegalFormatCodePointException) JavaClassName() string {
 	return "java.util.IllegalFormatCodePointException"
 }
+
+// equals to getStackTrace in java
+func (e IllegalFormatCodePointException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/illegal_format_conversion_exception.go b/java_exception/illegal_format_conversion_exception.go
index 83a4695..1ce2788 100644
--- a/java_exception/illegal_format_conversion_exception.go
+++ b/java_exception/illegal_format_conversion_exception.go
@@ -44,3 +44,8 @@ func (IllegalFormatConversionException) JavaClassName() string {
 func NewIllegalFormatConversionException(detailMessage string) *IllegalFormatConversionException {
 	return &IllegalFormatConversionException{DetailMessage: detailMessage}
 }
+
+// equals to getStackTrace in java
+func (e IllegalFormatConversionException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/illegal_format_flags_exception.go b/java_exception/illegal_format_flags_exception.go
index 4a2434f..a3ee18b 100644
--- a/java_exception/illegal_format_flags_exception.go
+++ b/java_exception/illegal_format_flags_exception.go
@@ -43,3 +43,8 @@ func (e IllegalFormatFlagsException) Error() string {
 func (IllegalFormatFlagsException) JavaClassName() string {
 	return "java.util.IllegalFormatFlagsException"
 }
+
+// equals to getStackTrace in java
+func (e IllegalFormatFlagsException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/illegal_format_precision_exception.go b/java_exception/illegal_format_precision_exception.go
index 71ab7b8..d57bba0 100644
--- a/java_exception/illegal_format_precision_exception.go
+++ b/java_exception/illegal_format_precision_exception.go
@@ -43,3 +43,8 @@ func (e IllegalFormatPrecisionException) Error() string {
 func (IllegalFormatPrecisionException) JavaClassName() string {
 	return "java.util.IllegalFormatPrecisionException"
 }
+
+// equals to getStackTrace in java
+func (e IllegalFormatPrecisionException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/illegal_format_width_exception.go b/java_exception/illegal_format_width_exception.go
index fca27cc..e32f200 100644
--- a/java_exception/illegal_format_width_exception.go
+++ b/java_exception/illegal_format_width_exception.go
@@ -43,3 +43,8 @@ func (IllegalFormatWidthException) JavaClassName() string {
 func NewIllegalFormatWidthException(w int) *IllegalFormatWidthException {
 	return &IllegalFormatWidthException{W: w}
 }
+
+// equals to getStackTrace in java
+func (e IllegalFormatWidthException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/illegal_monitor_state_exception.go b/java_exception/illegal_monitor_state_exception.go
index 0b1e314..4374afc 100644
--- a/java_exception/illegal_monitor_state_exception.go
+++ b/java_exception/illegal_monitor_state_exception.go
@@ -40,3 +40,8 @@ func (e IllegalMonitorStateException) Error() string {
 func (IllegalMonitorStateException) JavaClassName() string {
 	return "java.lang.IllegalMonitorStateException"
 }
+
+// equals to getStackTrace in java
+func (e IllegalMonitorStateException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/illegal_state_exception.go b/java_exception/illegal_state_exception.go
index 0e48485..88aa7c3 100644
--- a/java_exception/illegal_state_exception.go
+++ b/java_exception/illegal_state_exception.go
@@ -40,3 +40,8 @@ func (e IllegalStateException) Error() string {
 func (IllegalStateException) JavaClassName() string {
 	return "java.lang.IllegalStateException"
 }
+
+// equals to getStackTrace in java
+func (e IllegalStateException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/illegal_thread_state_exception.go b/java_exception/illegal_thread_state_exception.go
index 6f3db69..8aacdc5 100644
--- a/java_exception/illegal_thread_state_exception.go
+++ b/java_exception/illegal_thread_state_exception.go
@@ -40,3 +40,8 @@ func (e IllegalThreadStateException) Error() string {
 func (IllegalThreadStateException) JavaClassName() string {
 	return "java.lang.IllegalThreadStateException"
 }
+
+// equals to getStackTrace in java
+func (e IllegalThreadStateException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/illformed_locale_exception.go b/java_exception/illformed_locale_exception.go
index 142666d..baf9436 100644
--- a/java_exception/illformed_locale_exception.go
+++ b/java_exception/illformed_locale_exception.go
@@ -41,3 +41,8 @@ func (IllformedLocaleException) JavaClassName() string {
 func NewIllformedLocaleException(detailMessage string) *IllformedLocaleException {
 	return &IllformedLocaleException{DetailMessage: detailMessage}
 }
+
+// equals to getStackTrace in java
+func (e IllformedLocaleException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/incomplete_annotation_exception.go b/java_exception/incomplete_annotation_exception.go
index f11a45e..6543d36 100644
--- a/java_exception/incomplete_annotation_exception.go
+++ b/java_exception/incomplete_annotation_exception.go
@@ -42,3 +42,8 @@ func (e IncompleteAnnotationException) Error() string {
 func (IncompleteAnnotationException) JavaClassName() string {
 	return "java.lang.annotation.IncompleteAnnotationException"
 }
+
+// equals to getStackTrace in java
+func (e IncompleteAnnotationException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/index_out_of_bounds_exception.go b/java_exception/index_out_of_bounds_exception.go
index 7481fef..bd5349d 100644
--- a/java_exception/index_out_of_bounds_exception.go
+++ b/java_exception/index_out_of_bounds_exception.go
@@ -40,3 +40,8 @@ func (e IndexOutOfBoundsException) Error() string {
 func (IndexOutOfBoundsException) JavaClassName() string {
 	return "java.lang.IndexOutOfBoundsException"
 }
+
+// equals to getStackTrace in java
+func (e IndexOutOfBoundsException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/input_mismatch_exception.go b/java_exception/input_mismatch_exception.go
index 266b648..44e0eca 100644
--- a/java_exception/input_mismatch_exception.go
+++ b/java_exception/input_mismatch_exception.go
@@ -40,3 +40,8 @@ func (e InputMismatchException) Error() string {
 func (InputMismatchException) JavaClassName() string {
 	return "java.util.InputMismatchException"
 }
+
+// equals to getStackTrace in java
+func (e InputMismatchException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/instantiation_exception.go b/java_exception/instantiation_exception.go
index 8df5cb8..eb6de69 100644
--- a/java_exception/instantiation_exception.go
+++ b/java_exception/instantiation_exception.go
@@ -40,3 +40,8 @@ func (e InstantiationException) Error() string {
 func (InstantiationException) JavaClassName() string {
 	return "java.lang.InstantiationException"
 }
+
+// equals to getStackTrace in java
+func (e InstantiationException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/interrupted_exception.go b/java_exception/interrupted_exception.go
index a8f638b..00495b7 100644
--- a/java_exception/interrupted_exception.go
+++ b/java_exception/interrupted_exception.go
@@ -43,3 +43,8 @@ func (e InterruptedException) Error() string {
 func (InterruptedException) JavaClassName() string {
 	return "java.lang.InterruptedException"
 }
+
+// equals to getStackTrace in java
+func (e InterruptedException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/interrupted_io_exception.go b/java_exception/interrupted_io_exception.go
index c69d1b8..7ecb844 100644
--- a/java_exception/interrupted_io_exception.go
+++ b/java_exception/interrupted_io_exception.go
@@ -44,3 +44,8 @@ func (e InterruptedIOException) Error() string {
 func (InterruptedIOException) JavaClassName() string {
 	return "java.io.InterruptedIOException"
 }
+
+// equals to getStackTrace in java
+func (e InterruptedIOException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/invalid_class_exception.go b/java_exception/invalid_class_exception.go
index ebc2579..ca97120 100644
--- a/java_exception/invalid_class_exception.go
+++ b/java_exception/invalid_class_exception.go
@@ -48,3 +48,8 @@ func (e InvalidClassException) Error() string {
 func (InvalidClassException) JavaClassName() string {
 	return "java.io.InvalidClassException"
 }
+
+// equals to getStackTrace in java
+func (e InvalidClassException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/invalid_object_exception.go b/java_exception/invalid_object_exception.go
index 5080553..334116e 100644
--- a/java_exception/invalid_object_exception.go
+++ b/java_exception/invalid_object_exception.go
@@ -40,3 +40,8 @@ func (e InvalidObjectException) Error() string {
 func (InvalidObjectException) JavaClassName() string {
 	return "java.io.InvalidObjectException"
 }
+
+// equals to getStackTrace in java
+func (e InvalidObjectException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/invalid_preferences_format_exception.go b/java_exception/invalid_preferences_format_exception.go
index a264ccc..92c9600 100644
--- a/java_exception/invalid_preferences_format_exception.go
+++ b/java_exception/invalid_preferences_format_exception.go
@@ -40,3 +40,8 @@ func (e InvalidPreferencesFormatException) Error() string {
 func (InvalidPreferencesFormatException) JavaClassName() string {
 	return "java.util.prefs.InvalidPreferencesFormatException"
 }
+
+// equals to getStackTrace in java
+func (e InvalidPreferencesFormatException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/invalid_properties_format_exception.go b/java_exception/invalid_properties_format_exception.go
index ab0f4e7..56a4cc7 100644
--- a/java_exception/invalid_properties_format_exception.go
+++ b/java_exception/invalid_properties_format_exception.go
@@ -40,3 +40,8 @@ func (e InvalidPropertiesFormatException) Error() string {
 func (InvalidPropertiesFormatException) JavaClassName() string {
 	return "java.util.InvalidPropertiesFormatException"
 }
+
+// equals to getStackTrace in java
+func (e InvalidPropertiesFormatException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/invocation_target_exception.go b/java_exception/invocation_target_exception.go
index 08f54ba..d530ad0 100644
--- a/java_exception/invocation_target_exception.go
+++ b/java_exception/invocation_target_exception.go
@@ -41,3 +41,8 @@ func (e InvocationTargetException) Error() string {
 func (InvocationTargetException) JavaClassName() string {
 	return "java.lang.reflect.InvocationTargetException"
 }
+
+// equals to getStackTrace in java
+func (e InvocationTargetException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/io_exception.go b/java_exception/io_exception.go
index 10a81df..01f4ece 100644
--- a/java_exception/io_exception.go
+++ b/java_exception/io_exception.go
@@ -40,3 +40,8 @@ func (e IOException) Error() string {
 func (IOException) JavaClassName() string {
 	return "java.io.IOException"
 }
+
+// equals to getStackTrace in java
+func (e IOException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/jar_exception.go b/java_exception/jar_exception.go
index f0029a5..2a1ad50 100644
--- a/java_exception/jar_exception.go
+++ b/java_exception/jar_exception.go
@@ -40,3 +40,8 @@ func (e JarException) Error() string {
 func (JarException) JavaClassName() string {
 	return "java.util.jar.JarException"
 }
+
+// equals to getStackTrace in java
+func (e JarException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/lambda_conversion_exception.go b/java_exception/lambda_conversion_exception.go
index 4e0f504..b63e27e 100644
--- a/java_exception/lambda_conversion_exception.go
+++ b/java_exception/lambda_conversion_exception.go
@@ -43,3 +43,8 @@ func (e LambdaConversionException) Error() string {
 func (LambdaConversionException) JavaClassName() string {
 	return "java.lang.invoke.LambdaConversionException"
 }
+
+// equals to getStackTrace in java
+func (e LambdaConversionException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/malformed_parameterized_type_exception.go b/java_exception/malformed_parameterized_type_exception.go
index 0135f22..6b8aa3d 100644
--- a/java_exception/malformed_parameterized_type_exception.go
+++ b/java_exception/malformed_parameterized_type_exception.go
@@ -40,3 +40,8 @@ func (MalformedParameterizedTypeException) JavaClassName() string {
 func NewMalformedParameterizedTypeException(detailMessage string) *MalformedParameterizedTypeException {
 	return &MalformedParameterizedTypeException{DetailMessage: detailMessage}
 }
+
+// equals to getStackTrace in java
+func (e MalformedParameterizedTypeException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/malformed_parameters_exception.go b/java_exception/malformed_parameters_exception.go
index 49e3118..1b3a35d 100644
--- a/java_exception/malformed_parameters_exception.go
+++ b/java_exception/malformed_parameters_exception.go
@@ -40,3 +40,8 @@ func (MalformedParametersException) JavaClassName() string {
 func NewMalformedParametersException(detailMessage string) *MalformedParametersException {
 	return &MalformedParametersException{DetailMessage: detailMessage}
 }
+
+// equals to getStackTrace in java
+func (e MalformedParametersException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/missing_format_argument_exception.go b/java_exception/missing_format_argument_exception.go
index 281821e..b90968d 100644
--- a/java_exception/missing_format_argument_exception.go
+++ b/java_exception/missing_format_argument_exception.go
@@ -43,3 +43,8 @@ func (e MissingFormatArgumentException) Error() string {
 func (MissingFormatArgumentException) JavaClassName() string {
 	return "java.util.MissingFormatArgumentException"
 }
+
+// equals to getStackTrace in java
+func (e MissingFormatArgumentException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/missing_format_width_exception.go b/java_exception/missing_format_width_exception.go
index b22e8ad..2f3e87c 100644
--- a/java_exception/missing_format_width_exception.go
+++ b/java_exception/missing_format_width_exception.go
@@ -41,3 +41,8 @@ func (e MissingFormatWidthException) Error() string {
 func (MissingFormatWidthException) JavaClassName() string {
 	return "java.util.MissingFormatWidthException"
 }
+
+// equals to getStackTrace in java
+func (e MissingFormatWidthException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/missing_resource_exception.go b/java_exception/missing_resource_exception.go
index 0d0bab7..604d1ef 100644
--- a/java_exception/missing_resource_exception.go
+++ b/java_exception/missing_resource_exception.go
@@ -42,3 +42,8 @@ func (MissingResourceException) JavaClassName() string {
 func NewMissingResourceException(detailMessage, classname, key string) *MissingResourceException {
 	return &MissingResourceException{DetailMessage: detailMessage, ClassName: classname, Key: key}
 }
+
+// equals to getStackTrace in java
+func (e MissingResourceException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/negative_array_size_exception.go b/java_exception/negative_array_size_exception.go
index a8aeb84..538a5d6 100644
--- a/java_exception/negative_array_size_exception.go
+++ b/java_exception/negative_array_size_exception.go
@@ -40,3 +40,8 @@ func (e NegativeArraySizeException) Error() string {
 func (NegativeArraySizeException) JavaClassName() string {
 	return "java.lang.NegativeArraySizeException"
 }
+
+// equals to getStackTrace in java
+func (e NegativeArraySizeException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/no_such_element_exception.go b/java_exception/no_such_element_exception.go
index 3f8c8a7..dc56b74 100644
--- a/java_exception/no_such_element_exception.go
+++ b/java_exception/no_such_element_exception.go
@@ -40,3 +40,8 @@ func (NoSuchElementException) JavaClassName() string {
 func NewNoSuchElementException(detailMessage string) *NoSuchElementException {
 	return &NoSuchElementException{DetailMessage: detailMessage}
 }
+
+// equals to getStackTrace in java
+func (e NoSuchElementException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/no_such_field_exception.go b/java_exception/no_such_field_exception.go
index dddcbf2..ba292f1 100644
--- a/java_exception/no_such_field_exception.go
+++ b/java_exception/no_such_field_exception.go
@@ -40,3 +40,8 @@ func (e NoSuchFieldException) Error() string {
 func (NoSuchFieldException) JavaClassName() string {
 	return "java.lang.NoSuchFieldException"
 }
+
+// equals to getStackTrace in java
+func (e NoSuchFieldException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/no_such_method_exception.go b/java_exception/no_such_method_exception.go
index 05587f3..a34b57d 100644
--- a/java_exception/no_such_method_exception.go
+++ b/java_exception/no_such_method_exception.go
@@ -40,3 +40,8 @@ func (e NoSuchMethodException) Error() string {
 func (NoSuchMethodException) JavaClassName() string {
 	return "java.lang.NoSuchMethodException"
 }
+
+// equals to getStackTrace in java
+func (e NoSuchMethodException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/not_active_exception.go b/java_exception/not_active_exception.go
index 5d1d34a..48141d3 100644
--- a/java_exception/not_active_exception.go
+++ b/java_exception/not_active_exception.go
@@ -40,3 +40,8 @@ func (e NotActiveException) Error() string {
 func (NotActiveException) JavaClassName() string {
 	return "java.io.NotActiveException"
 }
+
+// equals to getStackTrace in java
+func (e NotActiveException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/not_serializable_exception.go b/java_exception/not_serializable_exception.go
index 3782df3..e77c84a 100644
--- a/java_exception/not_serializable_exception.go
+++ b/java_exception/not_serializable_exception.go
@@ -40,3 +40,8 @@ func (e NotSerializableException) Error() string {
 func (NotSerializableException) JavaClassName() string {
 	return "java.io.NotSerializableException"
 }
+
+// equals to getStackTrace in java
+func (e NotSerializableException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/null_pointer_exception.go b/java_exception/null_pointer_exception.go
index f3cb0a5..1686820 100644
--- a/java_exception/null_pointer_exception.go
+++ b/java_exception/null_pointer_exception.go
@@ -40,3 +40,8 @@ func (e NullPointerException) Error() string {
 func (e NullPointerException) JavaClassName() string {
 	return "java.lang.NullPointerException"
 }
+
+// equals to getStackTrace in java
+func (e NullPointerException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/number_format_exception.go b/java_exception/number_format_exception.go
index 2158bbc..36c4401 100644
--- a/java_exception/number_format_exception.go
+++ b/java_exception/number_format_exception.go
@@ -40,3 +40,8 @@ func (e NumberFormatException) Error() string {
 func (NumberFormatException) JavaClassName() string {
 	return "java.lang.NumberFormatException"
 }
+
+// equals to getStackTrace in java
+func (e NumberFormatException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/object_stream_exception.go b/java_exception/object_stream_exception.go
index 2e005d6..eaa0eb8 100644
--- a/java_exception/object_stream_exception.go
+++ b/java_exception/object_stream_exception.go
@@ -40,3 +40,8 @@ func (e ObjectStreamException) Error() string {
 func (ObjectStreamException) JavaClassName() string {
 	return "java.io.ObjectStreamException"
 }
+
+// equals to getStackTrace in java
+func (e ObjectStreamException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/optional_data_exception.go b/java_exception/optional_data_exception.go
index ab2dcdc..bc1424b 100644
--- a/java_exception/optional_data_exception.go
+++ b/java_exception/optional_data_exception.go
@@ -42,3 +42,8 @@ func (e OptionalDataException) Error() string {
 func (OptionalDataException) JavaClassName() string {
 	return "java.io.OptionalDataException"
 }
+
+// equals to getStackTrace in java
+func (e OptionalDataException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/reflective_operation_exception.go b/java_exception/reflective_operation_exception.go
index 70b1632..2db3fc2 100644
--- a/java_exception/reflective_operation_exception.go
+++ b/java_exception/reflective_operation_exception.go
@@ -40,3 +40,8 @@ func (e ReflectiveOperationException) Error() string {
 func (ReflectiveOperationException) JavaClassName() string {
 	return "java.lang.ReflectiveOperationException"
 }
+
+// equals to getStackTrace in java
+func (e ReflectiveOperationException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/rejected_execution_exception.go b/java_exception/rejected_execution_exception.go
index b03b385..940f676 100644
--- a/java_exception/rejected_execution_exception.go
+++ b/java_exception/rejected_execution_exception.go
@@ -40,3 +40,8 @@ func (RejectedExecutionException) JavaClassName() string {
 func NewRejectedExecutionException(detailMessage string) *RejectedExecutionException {
 	return &RejectedExecutionException{DetailMessage: detailMessage}
 }
+
+// equals to getStackTrace in java
+func (e RejectedExecutionException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/runtime_exception.go b/java_exception/runtime_exception.go
index 993e81b..5a8dff2 100644
--- a/java_exception/runtime_exception.go
+++ b/java_exception/runtime_exception.go
@@ -40,3 +40,8 @@ func (e RuntimeException) Error() string {
 func (RuntimeException) JavaClassName() string {
 	return "java.lang.RuntimeException"
 }
+
+// equals to getStackTrace in java
+func (e RuntimeException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/security_exception.go b/java_exception/security_exception.go
index efa3bb2..f06c741 100644
--- a/java_exception/security_exception.go
+++ b/java_exception/security_exception.go
@@ -40,3 +40,8 @@ func (e SecurityException) Error() string {
 func (SecurityException) JavaClassName() string {
 	return "java.lang.SecurityException"
 }
+
+// equals to getStackTrace in java
+func (e SecurityException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/stream_corrupted_exception.go b/java_exception/stream_corrupted_exception.go
index 5df3065..bf27914 100644
--- a/java_exception/stream_corrupted_exception.go
+++ b/java_exception/stream_corrupted_exception.go
@@ -40,3 +40,8 @@ func (e StreamCorruptedException) Error() string {
 func (StreamCorruptedException) JavaClassName() string {
 	return "java.io.StreamCorruptedException"
 }
+
+// equals to getStackTrace in java
+func (e StreamCorruptedException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/string_index_out_of_bounds_exception.go b/java_exception/string_index_out_of_bounds_exception.go
index fcada97..3dd0495 100644
--- a/java_exception/string_index_out_of_bounds_exception.go
+++ b/java_exception/string_index_out_of_bounds_exception.go
@@ -40,3 +40,8 @@ func (e StringIndexOutOfBoundsException) Error() string {
 func (StringIndexOutOfBoundsException) JavaClassName() string {
 	return "java.lang.StringIndexOutOfBoundsException"
 }
+
+// equals to getStackTrace in java
+func (e StringIndexOutOfBoundsException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/sync_failed_exception.go b/java_exception/sync_failed_exception.go
index 20f9b6b..e68103b 100644
--- a/java_exception/sync_failed_exception.go
+++ b/java_exception/sync_failed_exception.go
@@ -40,3 +40,8 @@ func (e SyncFailedException) Error() string {
 func (SyncFailedException) JavaClassName() string {
 	return "java.io.SyncFailedException"
 }
+
+// equals to getStackTrace in java
+func (e SyncFailedException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/timeout_exception.go b/java_exception/timeout_exception.go
index 3692e5d..831b108 100644
--- a/java_exception/timeout_exception.go
+++ b/java_exception/timeout_exception.go
@@ -40,3 +40,8 @@ func (e TimeoutException) Error() string {
 func (TimeoutException) JavaClassName() string {
 	return "java.util.concurrent.TimeoutException"
 }
+
+// equals to getStackTrace in java
+func (e TimeoutException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/too_many_listeners_exception.go b/java_exception/too_many_listeners_exception.go
index 93d2614..16c7f62 100644
--- a/java_exception/too_many_listeners_exception.go
+++ b/java_exception/too_many_listeners_exception.go
@@ -40,3 +40,8 @@ func (e TooManyListenersException) Error() string {
 func (TooManyListenersException) JavaClassName() string {
 	return "java.util.TooManyListenersException"
 }
+
+// equals to getStackTrace in java
+func (e TooManyListenersException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/type_not_present_exception.go b/java_exception/type_not_present_exception.go
index 09920ee..9700352 100644
--- a/java_exception/type_not_present_exception.go
+++ b/java_exception/type_not_present_exception.go
@@ -41,3 +41,8 @@ func (TypeNotPresentException) JavaClassName() string {
 func NewTypeNotPresentException(typeName string, detailMessage string) *TypeNotPresentException {
 	return &TypeNotPresentException{TypeName: typeName, DetailMessage: detailMessage}
 }
+
+// equals to getStackTrace in java
+func (e TypeNotPresentException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/unchecked_IO_exception.go b/java_exception/unchecked_IO_exception.go
index 86e09cf..c7a8c3b 100644
--- a/java_exception/unchecked_IO_exception.go
+++ b/java_exception/unchecked_IO_exception.go
@@ -44,3 +44,8 @@ func (e UncheckedIOException) Error() string {
 func (UncheckedIOException) JavaClassName() string {
 	return "java.io.UncheckedIOException"
 }
+
+// equals to getStackTrace in java
+func (e UncheckedIOException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/undeclared_throwable_exception.go b/java_exception/undeclared_throwable_exception.go
index 64ba396..1483c8a 100644
--- a/java_exception/undeclared_throwable_exception.go
+++ b/java_exception/undeclared_throwable_exception.go
@@ -41,3 +41,8 @@ func (UndeclaredThrowableException) JavaClassName() string {
 func NewUndeclaredThrowableException(detailMessage string) *UndeclaredThrowableException {
 	return &UndeclaredThrowableException{DetailMessage: detailMessage, UndeclaredThrowable: Throwable{}}
 }
+
+// equals to getStackTrace in java
+func (e UndeclaredThrowableException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/unknown_format_conversion_exception.go b/java_exception/unknown_format_conversion_exception.go
index 986074a..5b1fb26 100644
--- a/java_exception/unknown_format_conversion_exception.go
+++ b/java_exception/unknown_format_conversion_exception.go
@@ -43,3 +43,8 @@ func (e UnknownFormatConversionException) Error() string {
 func (UnknownFormatConversionException) JavaClassName() string {
 	return "java.util.UnknownFormatConversionException"
 }
+
+// equals to getStackTrace in java
+func (e UnknownFormatConversionException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/unknown_format_flags_exception.go b/java_exception/unknown_format_flags_exception.go
index eb07864..63da093 100644
--- a/java_exception/unknown_format_flags_exception.go
+++ b/java_exception/unknown_format_flags_exception.go
@@ -41,3 +41,8 @@ func (e UnknownFormatFlagsException) Error() string {
 func (UnknownFormatFlagsException) JavaClassName() string {
 	return "java.util.UnknownFormatFlagsException"
 }
+
+// equals to getStackTrace in java
+func (e UnknownFormatFlagsException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/unmodifiable_class_exception.go b/java_exception/unmodifiable_class_exception.go
index a7c75d5..12755db 100644
--- a/java_exception/unmodifiable_class_exception.go
+++ b/java_exception/unmodifiable_class_exception.go
@@ -43,3 +43,8 @@ func (e UnmodifiableClassException) Error() string {
 func (UnmodifiableClassException) JavaClassName() string {
 	return "java.lang.instrument.UnmodifiableClassException"
 }
+
+// equals to getStackTrace in java
+func (e UnmodifiableClassException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/unsupported_operation_exception.go b/java_exception/unsupported_operation_exception.go
index 01f3e06..d629eaf 100644
--- a/java_exception/unsupported_operation_exception.go
+++ b/java_exception/unsupported_operation_exception.go
@@ -40,3 +40,8 @@ func (e UnsupportedOperationException) Error() string {
 func (UnsupportedOperationException) JavaClassName() string {
 	return "java.lang.UnsupportedOperationException"
 }
+
+// equals to getStackTrace in java
+func (e UnsupportedOperationException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/unsupported_temporal_type_exception.go b/java_exception/unsupported_temporal_type_exception.go
index 9ebc180..91bc184 100644
--- a/java_exception/unsupported_temporal_type_exception.go
+++ b/java_exception/unsupported_temporal_type_exception.go
@@ -40,3 +40,8 @@ func (e UnsupportedTemporalTypeException) Error() string {
 func (UnsupportedTemporalTypeException) JavaClassName() string {
 	return "java.time.temporal.UnsupportedTemporalTypeException"
 }
+
+// equals to getStackTrace in java
+func (e UnsupportedTemporalTypeException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/utf_data_format_exception.go b/java_exception/utf_data_format_exception.go
index fe1c8e9..8c6d22f 100644
--- a/java_exception/utf_data_format_exception.go
+++ b/java_exception/utf_data_format_exception.go
@@ -40,3 +40,8 @@ func (e UTFDataFormatException) Error() string {
 func (UTFDataFormatException) JavaClassName() string {
 	return "java.io.UTFDataFormatException"
 }
+
+// equals to getStackTrace in java
+func (e UTFDataFormatException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/write_aborted_exception.go b/java_exception/write_aborted_exception.go
index cb03a1f..bbaa1e2 100644
--- a/java_exception/write_aborted_exception.go
+++ b/java_exception/write_aborted_exception.go
@@ -42,3 +42,8 @@ func (e WriteAbortedException) Error() string {
 func (WriteAbortedException) JavaClassName() string {
 	return "java.io.WriteAbortedException"
 }
+
+// equals to getStackTrace in java
+func (e WriteAbortedException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/wrong_method_type_exception.go b/java_exception/wrong_method_type_exception.go
index 7e47062..a0fcb0f 100644
--- a/java_exception/wrong_method_type_exception.go
+++ b/java_exception/wrong_method_type_exception.go
@@ -40,3 +40,8 @@ func (WrongMethodTypeException) JavaClassName() string {
 func NewWrongMethodTypeException(detailMessage string) *WrongMethodTypeException {
 	return &WrongMethodTypeException{DetailMessage: detailMessage}
 }
+
+// equals to getStackTrace in java
+func (e WrongMethodTypeException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/zip_exception.go b/java_exception/zip_exception.go
index e67aa1c..9a92704 100644
--- a/java_exception/zip_exception.go
+++ b/java_exception/zip_exception.go
@@ -40,3 +40,8 @@ func (e ZipException) Error() string {
 func (ZipException) JavaClassName() string {
 	return "java.util.zip.ZipException"
 }
+
+// equals to getStackTrace in java
+func (e ZipException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_exception/zone_rules_exception.go b/java_exception/zone_rules_exception.go
index 3b16471..871dba3 100644
--- a/java_exception/zone_rules_exception.go
+++ b/java_exception/zone_rules_exception.go
@@ -40,3 +40,8 @@ func (e ZoneRulesException) Error() string {
 func (ZoneRulesException) JavaClassName() string {
 	return "java.time.zone.ZoneRulesException"
 }
+
+// equals to getStackTrace in java
+func (e ZoneRulesException) GetStackTrace() []StackTraceElement {
+	return e.StackTrace
+}
diff --git a/java_sql_time.go b/java_sql_time.go
new file mode 100644
index 0000000..e6861bb
--- /dev/null
+++ b/java_sql_time.go
@@ -0,0 +1,145 @@
+/*
+ * 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 (
+	"io"
+	"reflect"
+)
+
+import (
+	perrors "github.com/pkg/errors"
+)
+
+import (
+	"github.com/apache/dubbo-go-hessian2/java_sql_time"
+)
+
+func init() {
+	RegisterPOJO(&java_sql_time.Date{})
+	RegisterPOJO(&java_sql_time.Time{})
+	SetJavaSqlTimeSerialize(&java_sql_time.Date{})
+	SetJavaSqlTimeSerialize(&java_sql_time.Time{})
+}
+
+// SetJavaSqlTimeSerialize register serializer for java.sql.Time & java.sql.Date
+func SetJavaSqlTimeSerialize(time java_sql_time.JavaSqlTime) {
+	name := time.JavaClassName()
+	SetSerializer(name, JavaSqlTimeSerializer{})
+}
+
+// JavaSqlTimeSerializer used to encode & decode java.sql.Time & java.sql.Date
+type JavaSqlTimeSerializer struct {
+}
+
+// nolint
+func (JavaSqlTimeSerializer) EncObject(e *Encoder, vv POJO) error {
+
+	var (
+		i         int
+		idx       int
+		err       error
+		clsDef    classInfo
+		className string
+		ptrV      reflect.Value
+	)
+
+	// ensure ptrV is pointer to know vv is type JavaSqlTime or not
+	ptrV = reflect.ValueOf(vv)
+	if reflect.TypeOf(vv).Kind() != reflect.Ptr {
+		ptrV = PackPtr(ptrV)
+	}
+	v, ok := ptrV.Interface().(java_sql_time.JavaSqlTime)
+	if !ok {
+		return perrors.New("can not be converted into java sql time object")
+	}
+	className = v.JavaClassName()
+	if className == "" {
+		return perrors.New("class name empty")
+	}
+	tValue := reflect.ValueOf(vv)
+	// check ref
+	if n, ok := e.checkRefMap(tValue); ok {
+		e.buffer = encRef(e.buffer, n)
+		return nil
+	}
+
+	// write object definition
+	idx = -1
+	for i = range e.classInfoList {
+		if v.JavaClassName() == e.classInfoList[i].javaName {
+			idx = i
+			break
+		}
+	}
+	if idx == -1 {
+		idx, ok = checkPOJORegistry(typeof(vv))
+		if !ok {
+			idx = RegisterPOJO(v)
+		}
+		_, clsDef, err = getStructDefByIndex(idx)
+		if err != nil {
+			return perrors.WithStack(err)
+		}
+		idx = len(e.classInfoList)
+		e.classInfoList = append(e.classInfoList, clsDef)
+		e.buffer = append(e.buffer, clsDef.buffer...)
+	}
+	e.buffer = e.buffer[0 : len(e.buffer)-1]
+	e.buffer = encInt32(e.buffer, 1)
+	e.buffer = encString(e.buffer, "value")
+
+	// write object instance
+	if byte(idx) <= OBJECT_DIRECT_MAX {
+		e.buffer = encByte(e.buffer, byte(idx)+BC_OBJECT_DIRECT)
+	} else {
+		e.buffer = encByte(e.buffer, BC_OBJECT)
+		e.buffer = encInt32(e.buffer, int32(idx))
+	}
+	e.buffer = encDateInMs(e.buffer, v.GetTime())
+	return nil
+}
+
+// nolint
+func (JavaSqlTimeSerializer) DecObject(d *Decoder, typ reflect.Type, cls classInfo) (interface{}, error) {
+
+	if typ.Kind() != reflect.Struct {
+		return nil, perrors.Errorf("wrong type expect Struct but get:%s", typ.String())
+	}
+
+	vRef := reflect.New(typ)
+	// add pointer ref so that ref the same object
+	d.appendRefs(vRef.Interface())
+
+	tag, err := d.readByte()
+	if err == io.EOF {
+		return nil, err
+	}
+	date, err := d.decDate(int32(tag))
+	if err != nil {
+		return nil, perrors.WithStack(err)
+	}
+	sqlTime := vRef.Interface()
+
+	result, ok := sqlTime.(java_sql_time.JavaSqlTime)
+	if !ok {
+		panic("result type is not sql time, please check the whether the conversion is ok")
+	}
+	result.SetTime(date)
+	return result, nil
+}
diff --git a/java_sql_time/date.go b/java_sql_time/date.go
new file mode 100644
index 0000000..3fdc400
--- /dev/null
+++ b/java_sql_time/date.go
@@ -0,0 +1,60 @@
+/*
+ * 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 java_sql_time
+
+import "time"
+
+type Date struct {
+	time.Time
+}
+
+func (d *Date) GetTime() time.Time {
+	return d.Time
+}
+
+func (d *Date) SetTime(time time.Time) {
+	d.Time = time
+}
+
+func (Date) JavaClassName() string {
+	return "java.sql.Date"
+}
+
+func (d *Date) ValueOf(dateStr string) error {
+	time, err := time.Parse("2006-01-02", dateStr)
+	if err != nil {
+		return err
+	}
+	d.Time = time
+	return nil
+}
+
+// nolint
+func (d *Date) Year() int {
+	return d.Time.Year()
+}
+
+// nolint
+func (d *Date) Month() time.Month {
+	return d.Time.Month()
+}
+
+// nolint
+func (d *Date) Day() int {
+	return d.Time.Day()
+}
diff --git a/java_sql_time/java_sql_time.go b/java_sql_time/java_sql_time.go
new file mode 100644
index 0000000..2f73864
--- /dev/null
+++ b/java_sql_time/java_sql_time.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 java_sql_time
+
+import "time"
+
+type JavaSqlTime interface {
+	// ValueOf parse time string which format likes '2006-01-02 15:04:05'
+	ValueOf(timeStr string) error
+	// SetTime for decode time
+	SetTime(time time.Time)
+	JavaClassName() string
+	// GetTime used to time
+	GetTime() time.Time
+}
diff --git a/java_sql_time/time.go b/java_sql_time/time.go
new file mode 100644
index 0000000..709cec8
--- /dev/null
+++ b/java_sql_time/time.go
@@ -0,0 +1,60 @@
+/*
+ * 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 java_sql_time
+
+import "time"
+
+type Time struct {
+	time.Time
+}
+
+func (Time) JavaClassName() string {
+	return "java.sql.Time"
+}
+
+func (t *Time) GetTime() time.Time {
+	return t.Time
+}
+
+// nolint
+func (t *Time) Hour() int {
+	return t.Time.Hour()
+}
+
+// nolint
+func (t *Time) Minute() int {
+	return t.Time.Minute()
+}
+
+// nolint
+func (t *Time) Second() int {
+	return t.Time.Second()
+}
+
+func (t *Time) SetTime(time time.Time) {
+	t.Time = time
+}
+
+func (t *Time) ValueOf(timeStr string) error {
+	time, err := time.Parse("15:04:05", timeStr)
+	if err != nil {
+		return err
+	}
+	t.Time = time
+	return nil
+}
diff --git a/java_unknown_exception.go b/java_unknown_exception.go
new file mode 100644
index 0000000..1b4196c
--- /dev/null
+++ b/java_unknown_exception.go
@@ -0,0 +1,88 @@
+/*
+ * 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 (
+	"fmt"
+	"sync"
+)
+
+import (
+	"github.com/apache/dubbo-go-hessian2/java_exception"
+)
+
+var exceptionCheckMutex sync.Mutex
+
+func checkAndGetException(cls classInfo) (structInfo, bool) {
+
+	if len(cls.fieldNameList) < 4 {
+		return structInfo{}, false
+	}
+	var (
+		throwable structInfo
+		ok        bool
+	)
+	var count = 0
+	for _, item := range cls.fieldNameList {
+		if item == "detailMessage" || item == "suppressedExceptions" || item == "stackTrace" || item == "cause" {
+			count++
+		}
+	}
+	// if have these 4 fields, it is throwable struct
+	if count == 4 {
+		exceptionCheckMutex.Lock()
+		defer exceptionCheckMutex.Unlock()
+		if throwable, ok = getStructInfo(cls.javaName); ok {
+			return throwable, true
+		}
+		RegisterPOJO(newBizException(cls.javaName))
+		if throwable, ok = getStructInfo(cls.javaName); ok {
+			return throwable, true
+		}
+	}
+	return throwable, count == 4
+}
+
+type UnknownException struct {
+	SerialVersionUID     int64
+	DetailMessage        string
+	SuppressedExceptions []java_exception.Throwabler
+	StackTrace           []java_exception.StackTraceElement
+	Cause                java_exception.Throwabler
+	name                 string
+}
+
+// NewThrowable is the constructor
+func newBizException(name string) *UnknownException {
+	return &UnknownException{name: name, StackTrace: []java_exception.StackTraceElement{}}
+}
+
+// Error output error message
+func (e UnknownException) Error() string {
+	return fmt.Sprintf("throw %v : %v", e.name, e.DetailMessage)
+}
+
+//JavaClassName  java fully qualified path
+func (e UnknownException) JavaClassName() string {
+	return e.name
+}
+
+// equals to getStackTrace in java
+func (e UnknownException) GetStackTrace() []java_exception.StackTraceElement {
+	return e.StackTrace
+}
diff --git a/list.go b/list.go
index 34c8aec..0eed874 100644
--- a/list.go
+++ b/list.go
@@ -29,6 +29,9 @@ import (
 import (
 	perrors "github.com/pkg/errors"
 )
+import (
+	"github.com/apache/dubbo-go-hessian2/java_exception"
+)
 
 var (
 	listTypeNameMapper = &sync.Map{}
@@ -46,6 +49,8 @@ var (
 		"date":             reflect.TypeOf(time.Time{}),
 		"object":           reflect.TypeOf([]Object{}).Elem(),
 		"java.lang.Object": reflect.TypeOf([]Object{}).Elem(),
+		// exception field StackTraceElement
+		"java.lang.StackTraceElement": reflect.TypeOf([]*java_exception.StackTraceElement{}).Elem(),
 	}
 )
 
@@ -279,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/map.go b/map.go
index 1b958c4..dc7a21b 100644
--- a/map.go
+++ b/map.go
@@ -113,14 +113,14 @@ func (e *Encoder) encMap(m interface{}) error {
 	value = UnpackPtrValue(value)
 	// check nil map
 	if value.Kind() == reflect.Ptr && !value.Elem().IsValid() {
-		e.buffer = encNull(e.buffer)
+		e.buffer = EncNull(e.buffer)
 		return nil
 	}
 
 	keys = value.MapKeys()
 	if len(keys) == 0 {
 		// fix: set nil for empty map
-		e.buffer = encNull(e.buffer)
+		e.buffer = EncNull(e.buffer)
 		return nil
 	}
 
@@ -268,9 +268,13 @@ func (d *Decoder) decMap(flag int32) (interface{}, error) {
 				if !ok {
 					return nil, perrors.Errorf("the type of map key must be string, but get %v", k)
 				}
-				fieldValue = instValue.FieldByName(fieldName)
-				if fieldValue.IsValid() {
-					fieldValue.Set(EnsureRawValue(v))
+				if instValue.Kind() == reflect.Map {
+					instValue.SetMapIndex(reflect.ValueOf(k), EnsureRawValue(v))
+				} else {
+					fieldValue = instValue.FieldByName(fieldName)
+					if fieldValue.IsValid() {
+						fieldValue.Set(EnsureRawValue(v))
+					}
 				}
 			}
 			_, err = d.readByte()
@@ -280,6 +284,9 @@ func (d *Decoder) decMap(flag int32) (interface{}, error) {
 			return inst, nil
 		} else {
 			m = make(map[interface{}]interface{})
+			classIndex := RegisterPOJOMapping(t, m)
+			d.appendClsDef(pojoRegistry.classInfoList[classIndex])
+
 			d.appendRefs(m)
 			for d.peekByte() != BC_END {
 				k, err = d.Decode()
diff --git a/null.go b/null.go
index 0b1fd7f..8d74d1b 100644
--- a/null.go
+++ b/null.go
@@ -20,6 +20,6 @@ package hessian
 /////////////////////////////////////////
 // Null
 /////////////////////////////////////////
-func encNull(b []byte) []byte {
+func EncNull(b []byte) []byte {
 	return append(b, BC_NULL)
 }
diff --git a/object.go b/object.go
index e2ef7b3..dcd8130 100644
--- a/object.go
+++ b/object.go
@@ -117,7 +117,7 @@ func (e *Encoder) encObject(v POJO) error {
 	vv = UnpackPtr(vv)
 	// check nil pointer
 	if !vv.IsValid() {
-		e.buffer = encNull(e.buffer)
+		e.buffer = EncNull(e.buffer)
 		return nil
 	}
 
@@ -547,6 +547,10 @@ func (d *Decoder) getStructDefByIndex(idx int) (reflect.Type, classInfo, error)
 	cls = d.classInfoList[idx]
 	s, ok = getStructInfo(cls.javaName)
 	if !ok {
+		// exception
+		if s, ok = checkAndGetException(cls); ok {
+			return s.typ, cls, nil
+		}
 		if !d.isSkip {
 			err = perrors.Errorf("can not find go type name %s in registry", cls.javaName)
 		}
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)
+}
diff --git a/pojo.go b/pojo.go
index be74bac..8ed2e42 100644
--- a/pojo.go
+++ b/pojo.go
@@ -115,17 +115,22 @@ func showPOJORegistry() {
 
 // RegisterPOJO Register a POJO instance. The return value is -1 if @o has been registered.
 func RegisterPOJO(o POJO) int {
+	return RegisterPOJOMapping(o.JavaClassName(), o)
+}
+
+// RegisterPOJOMapping Register a POJO instance. The return value is -1 if @o has been registered.
+func RegisterPOJOMapping(javaClassName string, o interface{}) int {
 	// # definition for an object (compact map)
 	// class-def  ::= 'C' string int string*
 	pojoRegistry.Lock()
 	defer pojoRegistry.Unlock()
 
-	if goName, ok := pojoRegistry.j2g[o.JavaClassName()]; ok {
+	if goName, ok := pojoRegistry.j2g[javaClassName]; ok {
 		return pojoRegistry.registry[goName].index
 	}
 
 	// JavaClassName shouldn't equal to goName
-	if _, ok := pojoRegistry.registry[o.JavaClassName()]; ok {
+	if _, ok := pojoRegistry.registry[javaClassName]; ok {
 		return -1
 	}
 
@@ -140,7 +145,7 @@ func RegisterPOJO(o POJO) int {
 	structInfo.typ = obtainValueType(o)
 
 	structInfo.goName = structInfo.typ.String()
-	structInfo.javaName = o.JavaClassName()
+	structInfo.javaName = javaClassName
 	structInfo.inst = o
 	pojoRegistry.j2g[structInfo.javaName] = structInfo.goName
 	registerTypeName(structInfo.goName, structInfo.javaName)
@@ -149,37 +154,37 @@ func RegisterPOJO(o POJO) int {
 	nextStruct := []reflect.Type{structInfo.typ}
 	for len(nextStruct) > 0 {
 		current := nextStruct[0]
-
-		for i := 0; i < current.NumField(); i++ {
-
-			// skip unexported anonymous filed
-			if current.Field(i).PkgPath != "" {
-				continue
-			}
-
-			structField := current.Field(i)
-
-			// skip ignored field
-			tagVal, hasTag := structField.Tag.Lookup(tagIdentifier)
-			if tagVal == `-` {
-				continue
+		if current.Kind() == reflect.Struct {
+			for i := 0; i < current.NumField(); i++ {
+				// skip unexported anonymous filed
+				if current.Field(i).PkgPath != "" {
+					continue
+				}
+
+				structField := current.Field(i)
+
+				// skip ignored field
+				tagVal, hasTag := structField.Tag.Lookup(tagIdentifier)
+				if tagVal == `-` {
+					continue
+				}
+
+				// flat anonymous field
+				if structField.Anonymous && structField.Type.Kind() == reflect.Struct {
+					nextStruct = append(nextStruct, structField.Type)
+					continue
+				}
+
+				var fieldName string
+				if hasTag {
+					fieldName = tagVal
+				} else {
+					fieldName = lowerCamelCase(structField.Name)
+				}
+
+				fieldList = append(fieldList, fieldName)
+				bBody = encString(bBody, fieldName)
 			}
-
-			// flat anonymous field
-			if structField.Anonymous && structField.Type.Kind() == reflect.Struct {
-				nextStruct = append(nextStruct, structField.Type)
-				continue
-			}
-
-			var fieldName string
-			if hasTag {
-				fieldName = tagVal
-			} else {
-				fieldName = lowerCamelCase(structField.Name)
-			}
-
-			fieldList = append(fieldList, fieldName)
-			bBody = encString(bBody, fieldName)
 		}
 
 		nextStruct = nextStruct[1:]
@@ -206,8 +211,8 @@ func RegisterPOJO(o POJO) int {
 	return structInfo.index
 }
 
-// easy for test
-func unRegisterPOJOs(os ...POJO) []int {
+// UnRegisterPOJOs unregister POJO instances. It is easy for test.
+func UnRegisterPOJOs(os ...POJO) []int {
 	arr := make([]int, len(os))
 	for i := range os {
 		arr[i] = unRegisterPOJO(os[i])
@@ -235,7 +240,7 @@ func unRegisterPOJO(o POJO) int {
 	return -1
 }
 
-func obtainValueType(o POJO) reflect.Type {
+func obtainValueType(o interface{}) reflect.Type {
 	v := reflect.ValueOf(o)
 	switch v.Kind() {
 	case reflect.Struct:
@@ -385,6 +390,10 @@ func createInstance(goName string) interface{} {
 		return nil
 	}
 
+	if s.typ.Kind() == reflect.Map {
+		return reflect.MakeMap(s.typ).Interface()
+	}
+
 	return reflect.New(s.typ).Interface()
 }
 
diff --git a/request.go b/request.go
index 020c789..25908cb 100644
--- a/request.go
+++ b/request.go
@@ -97,7 +97,8 @@ func getArgType(v interface{}) string {
 	case map[interface{}]interface{}:
 		// return  "java.util.HashMap"
 		return "java.util.Map"
-
+	case POJOEnum:
+		return v.(POJOEnum).JavaClassName()
 	//  Serialized tags for complex types
 	default:
 		t := reflect.TypeOf(v)
@@ -334,14 +335,13 @@ func unpackRequestBody(decoder *Decoder, reqObj interface{}) error {
 }
 
 func ToMapStringString(origin map[interface{}]interface{}) map[string]string {
-	dest := make(map[string]string)
+	dest := make(map[string]string, len(origin))
 	for k, v := range origin {
 		if kv, ok := k.(string); ok {
 			if v == nil {
 				dest[kv] = ""
 				continue
 			}
-
 			if vv, ok := v.(string); ok {
 				dest[kv] = vv
 			}
diff --git a/response.go b/response.go
index 0b2a97f..68f7c6b 100644
--- a/response.go
+++ b/response.go
@@ -43,7 +43,7 @@ type Response struct {
 // NewResponse create a new Response
 func NewResponse(rspObj interface{}, exception error, attachments map[string]string) *Response {
 	if attachments == nil {
-		attachments = make(map[string]string)
+		attachments = make(map[string]string, 8)
 	}
 	return &Response{
 		RspObj:      rspObj,
@@ -140,7 +140,7 @@ func packResponse(header DubboHeader, ret interface{}) ([]byte, error) {
 	}
 
 	byteArray = encoder.Buffer()
-	byteArray = encNull(byteArray) // if not, "java client" will throw exception  "unexpected end of file"
+	byteArray = EncNull(byteArray) // if not, "java client" will throw exception  "unexpected end of file"
 	pkgLen := len(byteArray)
 	if pkgLen > int(DEFAULT_LEN) { // 8M
 		return nil, perrors.Errorf("Data length %d too large, max payload %d", pkgLen, DEFAULT_LEN)
@@ -339,7 +339,7 @@ var versionInt = make(map[string]int)
 // https://github.com/apache/dubbo/blob/dubbo-2.7.1/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java#L96
 // isSupportResponseAttachment is for compatibility among some dubbo version
 func isSupportResponseAttachment(version string) bool {
-	if version == "" {
+	if len(version) == 0 {
 		return false
 	}
 
@@ -358,6 +358,9 @@ func isSupportResponseAttachment(version string) bool {
 }
 
 func version2Int(version string) int {
+	if len(version) == 0 {
+		return 0
+	}
 	var v = 0
 	varr := strings.Split(version, ".")
 	length := len(varr)


Test patch:
diff --git a/decode_test.go b/decode_test.go
index 3728fec..87f4604 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -24,6 +24,7 @@
 package hessian
 
 import (
+	"fmt"
 	"log"
 	"os"
 	"os/exec"
@@ -31,6 +32,14 @@ import (
 	"testing"
 )
 
+import (
+	"github.com/stretchr/testify/assert"
+)
+
+import (
+	"github.com/apache/dubbo-go-hessian2/java_exception"
+)
+
 const (
 	hessianJar = "test_hessian/target/test_hessian-1.0.0.jar"
 	testString = "hello, world! 你好，世界！"
@@ -109,7 +118,15 @@ func testDecodeJavaData(t *testing.T, method, className string, skip bool, expec
 	if ok {
 		r = tmp.value.Interface()
 	}
-	if !reflect.DeepEqual(r, expected) {
+	trow, o1 := r.(java_exception.Throwabler)
+	expe, o2 := expected.(java_exception.Throwabler)
+	if o1 && o2 {
+		log.Println(reflect.TypeOf(trow), reflect.TypeOf(trow).Elem().Name())
+		if trow.Error() == expe.Error() && reflect.TypeOf(trow).Elem().Name() == reflect.TypeOf(expe).Elem().Name() {
+			return
+		}
+		t.Errorf("%s: got %v, wanted %v", method, r, expected)
+	} else if !reflect.DeepEqual(r, expected) {
 		t.Errorf("%s: got %v, wanted %v", method, r, expected)
 	}
 }
@@ -127,3 +144,49 @@ func testDecodeFrameworkFunc(t *testing.T, method string, expected func(interfac
 	}
 	expected(r)
 }
+
+func TestUserDefindeException(t *testing.T) {
+	expect := &UnknownException{
+		DetailMessage: "throw UserDefindException",
+	}
+	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/hessian_test.go b/hessian_test.go
index e466cf2..b712838 100644
--- a/hessian_test.go
+++ b/hessian_test.go
@@ -199,8 +199,7 @@ func TestHessianCodec_ReadAttachments(t *testing.T) {
 	}
 	resp, err := doTestHessianEncodeHeader(t, PackageResponse, Response_OK, body)
 	assert.NoError(t, err)
-
-	unRegisterPOJOs(&CaseB{}, &CaseA{})
+	UnRegisterPOJOs(&CaseB{}, &CaseA{})
 	codecR1 := NewHessianCodec(bufio.NewReader(bytes.NewReader(resp)))
 	codecR2 := NewHessianCodec(bufio.NewReader(bytes.NewReader(resp)))
 	h := &DubboHeader{}
diff --git a/java8_time_test.go b/java8_time_test.go
new file mode 100644
index 0000000..d9d5985
--- /dev/null
+++ b/java8_time_test.go
@@ -0,0 +1,43 @@
+/*
+ * 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, Second: 6, Nano: 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})
+	doTestTime(t, "java8_ZoneOffset", &java8_time.ZoneOffSet{Seconds: 0})
+	doTestTime(t, "java8_OffsetDateTime", &java8_time.OffsetDateTime{DateTime: java8_time.LocalDateTime{Date: java8_time.LocalDate{Year: 2020, Month: 6, Day: 6}, Time: java8_time.LocalTime{Hour: 6, Minute: 6, Second: 6, Nano: 6}}, Offset: java8_time.ZoneOffSet{Seconds: -64800}})
+	doTestTime(t, "java8_OffsetTime", &java8_time.OffsetTime{LocalTime: java8_time.LocalTime{Hour: 6, Minute: 6, Second: 6, Nano: 6}, ZoneOffset: java8_time.ZoneOffSet{Seconds: -64800}})
+	doTestTime(t, "java8_ZonedDateTime", &java8_time.ZonedDateTime{DateTime: java8_time.LocalDateTime{Date: java8_time.LocalDate{Year: 2020, Month: 6, Day: 6}, Time: java8_time.LocalTime{Hour: 6, Minute: 6, Second: 6, Nano: 6}}, Offset: java8_time.ZoneOffSet{Seconds: 0}, ZoneId: "Z"})
+}
+
+func doTestTime(t *testing.T, method string, expected interface{}) {
+	testDecodeFramework(t, method, expected)
+}
diff --git a/java_sql_time_test.go b/java_sql_time_test.go
new file mode 100644
index 0000000..345cfab
--- /dev/null
+++ b/java_sql_time_test.go
@@ -0,0 +1,102 @@
+/*
+ * 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 (
+	"testing"
+	"time"
+)
+
+import (
+	"github.com/stretchr/testify/assert"
+)
+
+import (
+	"github.com/apache/dubbo-go-hessian2/java_sql_time"
+)
+
+func init() {
+	SetJavaSqlTimeSerialize(&java_sql_time.Date{})
+	SetJavaSqlTimeSerialize(&java_sql_time.Time{})
+}
+
+// test local time between go and java
+// go encode
+// java decode
+func TestJavaSqlTimeEncode(t *testing.T) {
+	sqlTime := time.Date(1997, 1, 1, 13, 15, 46, 0, time.UTC)
+	testSqlTime := java_sql_time.Time{Time: sqlTime}
+	testJavaDecode(t, "javaSql_encode_time", testSqlTime)
+
+	sqlDate := time.Date(2020, 8, 9, 0, 0, 0, 0, time.UTC)
+	testSqlDate := java_sql_time.Date{Time: sqlDate}
+	testJavaDecode(t, "javaSql_encode_date", &testSqlDate)
+}
+
+// test local time between go and java
+// java encode
+// go decode
+func TestJavaSqlTimeDecode(t *testing.T) {
+	sqlTime := time.Date(1997, 1, 1, 13, 15, 46, 0, time.UTC)
+	testSqlTime := java_sql_time.Time{Time: sqlTime}
+	testDecodeJavaSqlTime(t, "javaSql_decode_time", &testSqlTime)
+
+	sqlDate := time.Date(2020, 8, 9, 0, 0, 0, 0, time.UTC)
+	testDateTime := java_sql_time.Date{Time: sqlDate}
+	testDecodeJavaSqlTime(t, "javaSql_decode_date", &testDateTime)
+}
+
+func testDecodeJavaSqlTime(t *testing.T, method string, expected java_sql_time.JavaSqlTime) {
+	r, e := decodeJavaResponse(method, "", false)
+	if e != nil {
+		t.Errorf("%s: decode fail with error %v", method, e)
+		return
+	}
+	resultSqlTime, ok := r.(java_sql_time.JavaSqlTime)
+	if !ok {
+		t.Errorf("got error type:%v", r)
+	}
+	assert.Equal(t, resultSqlTime.GetTime().UnixNano(), expected.GetTime().UnixNano())
+}
+
+// test local time between go and go
+// go encode
+// go decode
+func TestJavaSqlTimeWithGo(t *testing.T) {
+	location, _ := time.ParseInLocation("2006-01-02 15:04:05", "1997-01-01 13:15:46", time.Local)
+	sqlTime := java_sql_time.Time{Time: location}
+	e := NewEncoder()
+	e.Encode(&sqlTime)
+	if len(e.Buffer()) == 0 {
+		t.Fail()
+	}
+	d := NewDecoder(e.Buffer())
+	resultSqlTime, _ := d.Decode()
+	assert.Equal(t, &sqlTime, resultSqlTime)
+
+	location, _ = time.ParseInLocation("2006-01-02 15:04:05", "2020-08-09 00:00:00", time.Local)
+	sqlDate := java_sql_time.Date{Time: location}
+	e = NewEncoder()
+	e.Encode(&sqlDate)
+	if len(e.Buffer()) == 0 {
+		t.Fail()
+	}
+	d = NewDecoder(e.Buffer())
+	resultSqlDate, _ := d.Decode()
+	assert.Equal(t, &sqlDate, resultSqlDate)
+}
diff --git a/java_unknown_exception_test.go b/java_unknown_exception_test.go
new file mode 100644
index 0000000..ea24321
--- /dev/null
+++ b/java_unknown_exception_test.go
@@ -0,0 +1,45 @@
+/*
+ * 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 (
+	"testing"
+)
+import (
+	"github.com/stretchr/testify/assert"
+)
+
+func TestCheckAndGetException(t *testing.T) {
+	clazzInfo1 := classInfo{
+		javaName:      "com.test.UserDefinedException",
+		fieldNameList: []string{"detailMessage", "code", "suppressedExceptions", "stackTrace", "cause"},
+	}
+	s, b := checkAndGetException(clazzInfo1)
+	assert.True(t, b)
+
+	assert.Equal(t, s.javaName, "com.test.UserDefinedException")
+	assert.Equal(t, s.goName, "hessian.UnknownException")
+
+	clazzInfo2 := classInfo{
+		javaName:      "com.test.UserDefinedException",
+		fieldNameList: []string{"detailMessage", "code", "suppressedExceptions", "cause"},
+	}
+	s, b = checkAndGetException(clazzInfo2)
+	assert.False(t, b)
+	assert.Equal(t, s, structInfo{})
+}
diff --git a/map_test.go b/map_test.go
index e349f7b..b63827d 100644
--- a/map_test.go
+++ b/map_test.go
@@ -96,3 +96,14 @@ func TestMapEncode(t *testing.T) {
 	testJavaDecode(t, "argUntypedMap_1", map[interface{}]interface{}{"a": int32(0)})
 	testJavaDecode(t, "argUntypedMap_2", map[interface{}]interface{}{int32(0): "a", int32(1): "b"})
 }
+
+func TestCustomMap(t *testing.T) {
+	testDecodeFramework(t, "customReplyMap", map[interface{}]interface{}{"a": int32(1), "b": int32(2)})
+
+	mapInMap := map[interface{}]interface{}{
+		"obj1": map[interface{}]interface{}{"a": int32(1)},
+		"obj2": map[interface{}]interface{}{"b": int32(2)},
+	}
+	testDecodeFramework(t, "customReplyMapInMap", mapInMap)
+	testDecodeFramework(t, "customReplyMapInMapJsonObject", mapInMap)
+}
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/request_test.go b/request_test.go
index b5886db..2b7f1f3 100644
--- a/request_test.go
+++ b/request_test.go
@@ -19,6 +19,7 @@ package hessian
 
 import (
 	"reflect"
+	"strconv"
 	"testing"
 	"time"
 )
@@ -27,6 +28,45 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
+type TestEnumGender JavaEnum
+
+const (
+	MAN JavaEnum = iota
+	WOMAN
+)
+
+var genderName = map[JavaEnum]string{
+	MAN:   "MAN",
+	WOMAN: "WOMAN",
+}
+
+var genderValue = map[string]JavaEnum{
+	"MAN":   MAN,
+	"WOMAN": WOMAN,
+}
+
+func (g TestEnumGender) JavaClassName() string {
+	return "com.ikurento.test.TestEnumGender"
+}
+
+func (g TestEnumGender) String() string {
+	s, ok := genderName[JavaEnum(g)]
+	if ok {
+		return s
+	}
+
+	return strconv.Itoa(int(g))
+}
+
+func (g TestEnumGender) EnumValue(s string) JavaEnum {
+	v, ok := genderValue[s]
+	if ok {
+		return v
+	}
+
+	return InvalidJavaEnum
+}
+
 func TestPackRequest(t *testing.T) {
 	bytes, err := packRequest(Service{
 		Path:      "test",
@@ -49,9 +89,9 @@ func TestPackRequest(t *testing.T) {
 
 func TestGetArgsTypeList(t *testing.T) {
 	type Test struct{}
-	str, err := getArgsTypeList([]interface{}{nil, 1, []int{2}, true, []bool{false}, "a", []string{"b"}, Test{}, &Test{}, []Test{}, map[string]Test{}})
+	str, err := getArgsTypeList([]interface{}{nil, 1, []int{2}, true, []bool{false}, "a", []string{"b"}, Test{}, &Test{}, []Test{}, map[string]Test{}, TestEnumGender(MAN)})
 	assert.NoError(t, err)
-	assert.Equal(t, "VJ[JZ[ZLjava/lang/String;[Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;Ljava/util/Map;", str)
+	assert.Equal(t, "VJ[JZ[ZLjava/lang/String;[Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;Ljava/util/Map;Lcom/ikurento/test/TestEnumGender;", str)
 }
 
 func TestDescRegex(t *testing.T) {
diff --git a/test_hessian/pom.xml b/test_hessian/pom.xml
index 6146e38..a4db3f1 100644
--- a/test_hessian/pom.xml
+++ b/test_hessian/pom.xml
@@ -47,6 +47,17 @@
             <artifactId>dubbo</artifactId>
             <version>2.6.5</version>
         </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.70</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..c012885 100644
--- a/test_hessian/src/main/java/test/Hessian.java
+++ b/test_hessian/src/main/java/test/Hessian.java
@@ -62,6 +62,34 @@ public class Hessian {
             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();
+        } else if (args[0].startsWith("javaSql_")) {
+            if (args[0].startsWith("javaSql_encode")) {
+
+                Hessian2Input input = new Hessian2Input(System.in);
+                Object o = input.readObject();
+
+                Method method = TestJavaSqlTime.class.getMethod(args[0], Object.class);
+                TestJavaSqlTime testJavaSqlTime = new TestJavaSqlTime();
+                System.out.print(method.invoke(testJavaSqlTime, o));
+            } else {
+                Method method = TestJavaSqlTime.class.getMethod(args[0]);
+                TestJavaSqlTime testJavaSqlTime = new TestJavaSqlTime();
+                Object object = method.invoke(testJavaSqlTime);
+
+                Hessian2Output output = new Hessian2Output(System.out);
+                output.writeObject(object);
+                output.flush();
+            }
+
         }
     }
 
diff --git a/test_hessian/src/main/java/test/TestCustomReply.java b/test_hessian/src/main/java/test/TestCustomReply.java
index 12fc411..62e3ea6 100644
--- a/test_hessian/src/main/java/test/TestCustomReply.java
+++ b/test_hessian/src/main/java/test/TestCustomReply.java
@@ -18,8 +18,12 @@
 package test;
 
 import com.alibaba.com.caucho.hessian.io.Hessian2Output;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.caucho.hessian.test.A0;
 import com.caucho.hessian.test.A1;
+import test.model.DateDemo;
+
 import java.io.OutputStream;
 import java.io.Serializable;
 import java.math.BigDecimal;
@@ -27,17 +31,16 @@ import java.math.BigInteger;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
-import test.model.DateDemo;
-
 
 public class TestCustomReply {
 
     private Hessian2Output output;
     private HashMap<Class<?>, String> typeMap;
 
-    TestCustomReply(OutputStream os) {
+    public TestCustomReply(OutputStream os) {
         output = new Hessian2Output(os);
 
         typeMap = new HashMap<>();
@@ -355,32 +358,32 @@ public class TestCustomReply {
     }
 
     public void customReplyTypedFixedList_BigInteger() throws Exception {
-        BigInteger[] integers = new BigInteger[] { 
-            new BigInteger("1234"), 
-            new BigInteger("12347890"), 
-            new BigInteger("123478901234"), 
-            new BigInteger("1234789012345678"), 
-            new BigInteger("123478901234567890"), 
-            new BigInteger("1234789012345678901234"), 
-            new BigInteger("12347890123456789012345678"), 
-            new BigInteger("123478901234567890123456781234"), 
-            new BigInteger("1234789012345678901234567812345678"), 
-            new BigInteger("12347890123456789012345678123456781234"), 
-            new BigInteger("-12347890123456789012345678123456781234"), 
-            new BigInteger("0"), 
+        BigInteger[] integers = new BigInteger[]{
+                new BigInteger("1234"),
+                new BigInteger("12347890"),
+                new BigInteger("123478901234"),
+                new BigInteger("1234789012345678"),
+                new BigInteger("123478901234567890"),
+                new BigInteger("1234789012345678901234"),
+                new BigInteger("12347890123456789012345678"),
+                new BigInteger("123478901234567890123456781234"),
+                new BigInteger("1234789012345678901234567812345678"),
+                new BigInteger("12347890123456789012345678123456781234"),
+                new BigInteger("-12347890123456789012345678123456781234"),
+                new BigInteger("0"),
         };
         output.writeObject(integers);
         output.flush();
     }
 
     public void customReplyTypedFixedList_CustomObject() throws Exception {
-        Object[] objects = new Object[] {
-            new BigInteger("1234"),
-            new BigInteger("-12347890"),
-            new BigInteger("0"),
-            new BigDecimal("123.4"),
-            new BigDecimal("-123.45"),
-            new BigDecimal("0"),
+        Object[] objects = new Object[]{
+                new BigInteger("1234"),
+                new BigInteger("-12347890"),
+                new BigInteger("0"),
+                new BigDecimal("123.4"),
+                new BigDecimal("-123.45"),
+                new BigDecimal("0"),
         };
         output.writeObject(objects);
         output.flush();
@@ -473,6 +476,37 @@ public class TestCustomReply {
         output.writeObject(set);
         output.flush();
     }
+
+    public void customReplyMap() throws Exception {
+        Map<String, Object> map = new HashMap<String, Object>(4);
+        map.put("a", 1);
+        map.put("b", 2);
+        output.writeObject(map);
+        output.flush();
+    }
+
+    public Map<String, Object> mapInMap() throws Exception {
+        Map<String, Object> map1 = new HashMap<String, Object>();
+        map1.put("a", 1);
+        Map<String, Object> map2 = new HashMap<String, Object>();
+        map2.put("b", 2);
+
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("obj1", map1);
+        map.put("obj2", map2);
+        return map;
+    }
+
+    public void customReplyMapInMap() throws Exception {
+        output.writeObject(mapInMap());
+        output.flush();
+    }
+
+    public void customReplyMapInMapJsonObject() throws Exception {
+        JSONObject json = JSON.parseObject(JSON.toJSONString(mapInMap()));
+        output.writeObject(json);
+        output.flush();
+    }
 }
 
 interface Leg {
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..779fe5e
--- /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, 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("Z");
+    }
+
+    public static ZoneOffset java8_ZoneOffset() {
+        return ZoneOffset.of("Z");
+    }
+
+}
diff --git a/test_hessian/src/main/java/test/TestJavaSqlTime.java b/test_hessian/src/main/java/test/TestJavaSqlTime.java
new file mode 100644
index 0000000..5316a88
--- /dev/null
+++ b/test_hessian/src/main/java/test/TestJavaSqlTime.java
@@ -0,0 +1,45 @@
+/*
+ * 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.sql.Date;
+import java.sql.Time;
+
+public class TestJavaSqlTime {
+
+    public Object javaSql_decode_date() {
+        return new Date(1596931200000L);
+    }
+
+    public Object javaSql_decode_time() {
+        return new Time(852124546000L);
+    }
+
+
+    public TestJavaSqlTime() {
+    }
+
+    public static Object javaSql_encode_time(Object v) {
+        return v.equals(new Time(852124546000L));
+    }
+
+    public boolean javaSql_encode_date(Object v) {
+        return v.equals(new Date(1596931200000L));
+    }
+
+}
diff --git a/test_hessian/src/main/java/test/TestThrowable.java b/test_hessian/src/main/java/test/TestThrowable.java
index 20652ff..3647e67 100644
--- a/test_hessian/src/main/java/test/TestThrowable.java
+++ b/test_hessian/src/main/java/test/TestThrowable.java
@@ -409,4 +409,8 @@ public class TestThrowable {
     return new AnnotationTypeMismatchException(Override.class.getEnclosingMethod(), "AnnotationTypeMismatchException");
   }
 
+  public static Object throw_UserDefindException() {
+      return new UserDefindException("throw UserDefindException");
+  }
+
 }
diff --git a/test_hessian/src/main/java/test/UserDefindException.java b/test_hessian/src/main/java/test/UserDefindException.java
new file mode 100644
index 0000000..26d1db1
--- /dev/null
+++ b/test_hessian/src/main/java/test/UserDefindException.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+public class UserDefindException extends RuntimeException{
+    public UserDefindException(String dd){
+        super(dd);
+    }
+}
\ No newline at end of file
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();
+    }
+}