Repository: alibaba/fastjson2
Pull request #3236 (2024-12-31 19:07:03)

Bump org.apache.maven.plugins:maven-site-plugin from 3.20.0 to 3.21.0
Bumps [org.apache.maven.plugins:maven-site-plugin](https://github.com/apache/maven-site-plugin) from 3.20.0 to 3.21.0.
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/apache/maven-site-plugin/commit/43f73ece16b84f5d8653bc9e1e2b256efc2ac984"><code>43f73ec</code></a> [maven-release-plugin] prepare release maven-site-plugin-3.21.0</li>
<li><a href="https://github.com/apache/maven-site-plugin/commit/a2880fb59e903ff6047296ca7d8715e04c35c49e"><code>a2880fb</code></a> [MSITE-1024] Remove IT for MSITE-901</li>
<li><a href="https://github.com/apache/maven-site-plugin/commit/6171e7d4aa55cbc4c2159df1d7014adb4ae43901"><code>6171e7d</code></a> [MSITE-1023] Upgrade plugins and components (in ITs)</li>
<li><a href="https://github.com/apache/maven-site-plugin/commit/efd8a57a15e7fb49d05068533de72df8291b25ed"><code>efd8a57</code></a> [MSITE-1022] Upgrade to Maven Reporting Exec 2.0.0</li>
<li><a href="https://github.com/apache/maven-site-plugin/commit/f5c5fc9547803c46d8173efee25e211642ca52f2"><code>f5c5fc9</code></a> Fix typos in history.apt and faq.fml</li>
<li><a href="https://github.com/apache/maven-site-plugin/commit/64c403538fde8b57745aaebb2c3a244f938d3281"><code>64c4035</code></a> [MSITE-1021] Bump doxiaSitetoolsVersion from 2.0.0-M19 to 2.0.0</li>
<li><a href="https://github.com/apache/maven-site-plugin/commit/e26765c7fd8cbc09a8cf458f8abf526c0a1b10f7"><code>e26765c</code></a> [MSITE-1020] Bump org.apache.maven.reporting:maven-reporting-api from 4.0.0-M...</li>
<li><a href="https://github.com/apache/maven-site-plugin/commit/354cf19e4f047d0222d5d29146b69e789445d3e6"><code>354cf19</code></a> [MSITE-1019] Bump doxiaVersion from 2.0.0-M12 to 2.0.0</li>
<li><a href="https://github.com/apache/maven-site-plugin/commit/67b568a9b7ff53c16536fde707254d131671c406"><code>67b568a</code></a> Use '<a href="https://github.com/project"><code>@​project</code></a>.' instead of '<a href="https://github.com/pom"><code>@​pom</code></a>.' expression prefix</li>
<li><a href="https://github.com/apache/maven-site-plugin/commit/fdfd8071f598aeb5b7f92cc1e4d13080302d0653"><code>fdfd807</code></a> Add version 3.20.0 to plugin history</li>
<li>Additional commits viewable in <a href="https://github.com/apache/maven-site-plugin/compare/maven-site-plugin-3.20.0...maven-site-plugin-3.21.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.apache.maven.plugins:maven-site-plugin&package-manager=maven&previous-version=3.20.0&new-version=3.21.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReader.java b/core/src/main/java/com/alibaba/fastjson2/JSONReader.java
index 35a1ec348..da75aa902 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONReader.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONReader.java
@@ -487,6 +487,7 @@ public abstract class JSONReader
             case ')':
             case '_':
             case ',':
+            case '~':
                 return (char) c;
             default:
                 throw new JSONException(info("unclosed.str '\\" + (char) c));
@@ -2245,6 +2246,7 @@ public abstract class JSONReader
             throw new JSONException("level too large : " + level);
         }
 
+        Map innerMap = null;
         Map object;
         if (context.objectSupplier == null) {
             if ((context.features & Feature.UseNativeObject.mask) != 0) {
@@ -2254,6 +2256,7 @@ public abstract class JSONReader
             }
         } else {
             object = context.objectSupplier.get();
+            innerMap = TypeUtils.getInnerMap(object);
         }
 
         for (int i = 0; ; ++i) {
@@ -2353,7 +2356,12 @@ public abstract class JSONReader
                 continue;
             }
 
-            Object origin = object.put(name, val);
+            Object origin;
+            if (innerMap != null) {
+                origin = innerMap.put(name, val);
+            } else {
+                origin = object.put(name, val);
+            }
             if (origin != null) {
                 if ((context.features & Feature.DuplicateKeyValueAsArray.mask) != 0) {
                     if (origin instanceof Collection) {
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderJSONB.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderJSONB.java
index 830e69612..cddb581da 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderJSONB.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderJSONB.java
@@ -195,32 +195,27 @@ final class JSONReaderJSONB
     }
 
     public int readLength() {
-        byte type = bytes[offset++];
+        byte[] bytes = this.bytes;
+        int offset = this.offset;
+        int type = bytes[offset++];
         if (type >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
-            return type;
-        }
-
-        if (type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX) {
-            return ((type - BC_INT32_BYTE_ZERO) << 8)
-                    + (bytes[offset++] & 0xFF);
-        }
-
-        if (type >= BC_INT32_SHORT_MIN && type <= BC_INT32_SHORT_MAX) {
-            int len = getInt3(bytes, offset, type);
+            // noop
+        } else if (type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX) {
+            type = ((type - BC_INT32_BYTE_ZERO) << 8) + (bytes[offset++] & 0xFF);
+        } else if (type >= BC_INT32_SHORT_MIN && type <= BC_INT32_SHORT_MAX) {
+            type = getInt3(bytes, offset, type);
             offset += 2;
-            return len;
-        }
-
-        if (type == BC_INT32) {
-            int len = getInt(bytes, offset);
+        } else if (type == BC_INT32) {
+            type = getInt(bytes, offset);
             offset += 4;
-            if (len > 1024 * 1024 * 256) {
+            if (type > 1024 * 1024 * 256) {
                 throw new JSONException("input length overflow");
             }
-            return len;
+        } else {
+            throw notSupportType((byte) type);
         }
-
-        throw notSupportType(type);
+        this.offset = offset;
+        return type;
     }
 
     static int getInt3(byte[] bytes, int offset, int type) {
@@ -231,12 +226,10 @@ final class JSONReaderJSONB
 
     @Override
     public boolean isArray() {
-        if (offset >= bytes.length) {
-            return false;
-        }
-
-        byte type = bytes[offset];
-        return type >= BC_ARRAY_FIX_MIN && type <= BC_ARRAY;
+        byte type;
+        return offset < end
+                && (type = bytes[offset]) >= BC_ARRAY_FIX_MIN
+                && type <= BC_ARRAY;
     }
 
     @Override
@@ -252,7 +245,7 @@ final class JSONReaderJSONB
 
     @Override
     public boolean isString() {
-        return offset < bytes.length
+        return offset < end
                 && (type = bytes[offset]) >= BC_STR_ASCII_FIX_MIN;
     }
 
@@ -278,33 +271,32 @@ final class JSONReaderJSONB
 
     @Override
     public boolean nextIfObjectStart() {
+        int offset = this.offset;
         if (bytes[offset] != BC_OBJECT) {
             return false;
         }
-        offset++;
+        this.offset = offset + 1;
         return true;
     }
 
     @Override
     public boolean nextIfObjectEnd() {
+        int offset = this.offset;
         if (bytes[offset] != BC_OBJECT_END) {
             return false;
         }
-        offset++;
+        this.offset = offset + 1;
         return true;
     }
 
     @Override
     public boolean nextIfNullOrEmptyString() {
-        if (bytes[offset] == BC_NULL) {
-            offset++;
-            return true;
-        }
-
-        if (bytes[offset] != BC_STR_ASCII_FIX_MIN) {
+        int offset = this.offset;
+        byte bc = bytes[offset];
+        if (bc != BC_NULL && bc != BC_STR_ASCII_FIX_MIN) {
             return false;
         }
-        offset += 1;
+        this.offset = offset + 1;
         return true;
     }
 
@@ -2632,23 +2624,23 @@ final class JSONReaderJSONB
         throw notSupportType(strtype);
     }
 
-    private static JSONException notSupportType(byte type) {
+    static JSONException notSupportType(byte type) {
         return new JSONException("name not support input : " + typeName(type));
     }
 
-    private JSONException notSupportString() {
+    JSONException notSupportString() {
         throw new JSONException("readString not support type " + typeName(strtype) + ", offset " + offset + "/" + bytes.length);
     }
 
-    private JSONException readInt32ValueError(byte type) {
+    JSONException readInt32ValueError(byte type) {
         throw new JSONException("readInt32Value not support " + typeName(type) + ", offset " + offset + "/" + bytes.length);
     }
 
-    private JSONException readInt64ValueError(byte type) {
+    JSONException readInt64ValueError(byte type) {
         throw new JSONException("readInt64Value not support " + typeName(type) + ", offset " + offset + "/" + bytes.length);
     }
 
-    private JSONException readStringError() {
+    JSONException readStringError() {
         throw new JSONException("string value not support input " + typeName(type) + " offset " + offset + "/" + bytes.length);
     }
 
@@ -2994,18 +2986,14 @@ final class JSONReaderJSONB
             this.strlen = strlen;
 
             if (strlen >= 0) {
-                if (STRING_CREATOR_JDK8 != null) {
-                    char[] chars = new char[strlen];
-                    for (int i = 0; i < strlen; ++i) {
-                        chars[i] = (char) (bytes[offset + i] & 0xff);
-                    }
-                    offset += strlen;
-                    str = STRING_CREATOR_JDK8.apply(chars, Boolean.TRUE);
-                } else if (STRING_CREATOR_JDK11 != null) {
+                if (STRING_CREATOR_JDK11 != null) {
                     byte[] chars = new byte[strlen];
                     System.arraycopy(bytes, offset, chars, 0, strlen);
                     str = STRING_CREATOR_JDK11.apply(chars, LATIN1);
                     offset += strlen;
+                } else if (STRING_CREATOR_JDK8 != null) {
+                    str = readStringJDK8(strlen, bytes);
+                    offset += strlen;
                 }
             }
 
@@ -3024,6 +3012,14 @@ final class JSONReaderJSONB
         return readStringNonAscii();
     }
 
+    private String readStringJDK8(int strlen, byte[] bytes) {
+        char[] chars = new char[strlen];
+        for (int i = 0; i < strlen; ++i) {
+            chars[i] = (char) (bytes[offset + i] & 0xff);
+        }
+        return STRING_CREATOR_JDK8.apply(chars, Boolean.TRUE);
+    }
+
     private String readStringNonAscii() {
         String str = null;
         Charset charset;
@@ -3596,32 +3592,30 @@ final class JSONReaderJSONB
     public int readInt32Value() {
         final byte[] bytes = this.bytes;
         int offset = this.offset;
-        final byte type = bytes[offset++];
-
-        int int32Value;
+        int type = bytes[offset++]; // reuse type as value
         if (type >= BC_INT32_NUM_MIN && type <= BC_INT32_NUM_MAX) {
-            int32Value = type;
+            // noop
         } else if (type >= BC_INT32_BYTE_MIN && type <= BC_INT32_BYTE_MAX) {
-            int32Value = ((type - BC_INT32_BYTE_ZERO) << 8)
+            type = ((type - BC_INT32_BYTE_ZERO) << 8)
                     + (bytes[offset] & 0xFF);
             offset += 1;
         } else if (type >= BC_INT32_SHORT_MIN && type <= BC_INT32_SHORT_MAX) {
-            int32Value = ((type - BC_INT32_SHORT_ZERO) << 16)
+            type = ((type - BC_INT32_SHORT_ZERO) << 16)
                     + ((bytes[offset] & 0xFF) << 8)
                     + (bytes[offset + 1] & 0xFF);
             offset += 2;
         } else if (type == BC_INT32) {
-            int32Value = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+            type = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
             if (!BIG_ENDIAN) {
-                int32Value = Integer.reverseBytes(int32Value);
+                type = Integer.reverseBytes(type);
             }
             offset += 4;
         } else {
             this.offset = offset;
-            return readInt32Value0(bytes, type);
+            return readInt32Value0(bytes, (byte) type);
         }
         this.offset = offset;
-        return int32Value;
+        return type;
     }
 
     private int readInt32Value0(byte[] bytes, byte type) {
@@ -3854,12 +3848,7 @@ final class JSONReaderJSONB
                     (char) (bytes[offset + 1] & 0xff)
             );
         } else if (STRING_CREATOR_JDK8 != null) {
-            char[] chars = new char[strlen];
-            for (int i = 0; i < strlen; ++i) {
-                chars[i] = (char) (bytes[offset + i] & 0xff);
-            }
-
-            str = STRING_CREATOR_JDK8.apply(chars, Boolean.TRUE);
+            str = readStringJDK8(strlen, bytes);
         } else {
             str = new String(bytes, offset, strlen, ISO_8859_1);
         }
@@ -4999,14 +4988,17 @@ final class JSONReaderJSONB
 
     @Override
     public ZonedDateTime readZonedDateTime() {
+        byte[] bytes = this.bytes;
         int type = bytes[offset++];
         if (type == BC_TIMESTAMP_WITH_TIMEZONE) {
-            int year = (bytes[offset++] << 8) + (bytes[offset++] & 0xFF);
-            int month = bytes[offset++];
-            int dayOfMonth = bytes[offset++];
-            int hour = bytes[offset++];
-            int minute = bytes[offset++];
-            int second = bytes[offset++];
+            int offset = this.offset;
+            int year = (bytes[offset] << 8) + (bytes[offset + 1] & 0xFF);
+            int month = bytes[offset + 2];
+            int dayOfMonth = bytes[offset + 3];
+            int hour = bytes[offset + 4];
+            int minute = bytes[offset + 5];
+            int second = bytes[offset + 6];
+            this.offset = offset + 7;
             int nano = readInt32Value();
             LocalDateTime ldt = LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nano);
 
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
index f2164d013..ce37b465e 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
@@ -31,6 +31,7 @@ public abstract class JSONWriter
     static final long WRITE_ARRAY_NULL_MASK = NullAsDefaultValue.mask | WriteNullListAsEmpty.mask;
     static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
     static final byte PRETTY_NON = 0, PRETTY_TAB = 1, PRETTY_2_SPACE = 2, PRETTY_4_SPACE = 4;
+    static final long NONE_DIRECT_FEATURES = ReferenceDetection.mask | NotWriteEmptyArray.mask | NotWriteDefaultValue.mask;
 
     public final Context context;
     public final boolean utf8;
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java
index ebb27c3b0..b5994d9e0 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java
@@ -33,7 +33,7 @@ final class JSONWriterJSONB
     static final long WRITE_ENUM_USING_STRING_MASK = WriteEnumUsingToString.mask | WriteEnumsUsingName.mask;
 
     private final CacheItem cacheItem;
-    private byte[] bytes;
+    byte[] bytes;
     private TLongIntHashMap symbols;
     private int symbolIndex;
 
@@ -2087,10 +2087,14 @@ final class JSONWriterJSONB
             return;
         }
 
+        String zoneIdStr = dateTime.getOffset().getId();
+        int strlen = zoneIdStr.length();
+
         int off = this.off;
         byte[] bytes = this.bytes;
-        if (off + 13 > bytes.length) {
-            bytes = grow(off + 13);
+        int minCapacity = off + 14 + strlen;
+        if (minCapacity > bytes.length) {
+            bytes = grow(minCapacity);
         }
 
         bytes[off] = BC_TIMESTAMP_WITH_TIMEZONE;
@@ -2104,15 +2108,11 @@ final class JSONWriterJSONB
         bytes[off + 7] = (byte) dateTime.getSecond();
         off += 8;
 
-        this.off = off + writeInt32(bytes, off, dateTime.getNano());
+        off += writeInt32(bytes, off, dateTime.getNano());
 
-        ZoneId zoneId = dateTime.getOffset();
-        String zoneIdStr = zoneId.getId();
-        if (zoneIdStr.equals(OFFSET_8_ZONE_ID_NAME)) {
-            writeRaw(OFFSET_8_ZONE_ID_NAME_BYTES);
-        } else {
-            writeString(zoneIdStr);
-        }
+        bytes[off++] = (byte) (strlen + BC_STR_ASCII_FIX_MIN);
+        zoneIdStr.getBytes(0, strlen, bytes, off);
+        this.off = off + strlen;
     }
 
     @Override
@@ -2310,18 +2310,13 @@ final class JSONWriterJSONB
     @Override
     public void writeReference(String path) {
         int off = this.off;
+        byte[] bytes = this.bytes;
         if (off == bytes.length) {
-            ensureCapacity(off + 1);
+            bytes = grow(off + 1);
         }
         bytes[off] = BC_REFERENCE;
         this.off = off + 1;
-
-        if (path == this.lastReference) {
-            writeString("#-1");
-        } else {
-            writeString(path);
-        }
-
+        writeString(path == this.lastReference ? "#-1" : path);
         this.lastReference = path;
     }
 
@@ -2718,7 +2713,7 @@ final class JSONWriterJSONB
 
     @Override
     public String toString() {
-        if (bytes.length == 0) {
+        if (off == 0) {
             return "<empty>";
         }
 
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
index 45a868560..97383c1c2 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
@@ -26,7 +26,8 @@ import static com.alibaba.fastjson2.util.TypeUtils.*;
 
 class JSONWriterUTF16
         extends JSONWriter {
-    static final char[] REF_PREF = "{\"$ref\":".toCharArray();
+    static final long REF_0, REF_1;
+    static final int QUOTE2_COLON, QUOTE_COLON;
     static final int[] HEX256;
     static {
         int[] digits = new int[16 * 16];
@@ -47,6 +48,14 @@ class JSONWriterUTF16
         }
 
         HEX256 = digits;
+
+        // char[] chars = new char[] {'\"', ':'};
+        char[] chars = {'{', '"', '$', 'r', 'e', 'f', '"', ':'};
+        REF_0 = UNSAFE.getLong(chars, ARRAY_CHAR_BASE_OFFSET);
+        REF_1 = UNSAFE.getLong(chars, ARRAY_CHAR_BASE_OFFSET + 8);
+        QUOTE2_COLON = UNSAFE.getInt(chars, ARRAY_CHAR_BASE_OFFSET + 12);
+        chars[6] = '\'';
+        QUOTE_COLON = UNSAFE.getInt(chars, ARRAY_CHAR_BASE_OFFSET + 12);
     }
 
     protected char[] chars;
@@ -1155,11 +1164,18 @@ class JSONWriterUTF16
     @Override
     public final void writeReference(String path) {
         this.lastReference = path;
-
-        writeRaw(REF_PREF, 0, REF_PREF.length);
-        writeString(path);
         int off = this.off;
         char[] chars = this.chars;
+        if (off + 9 > chars.length) {
+            chars = grow(off + 9);
+        }
+        long address = ARRAY_BYTE_BASE_OFFSET + ((long) off << 1);
+        UNSAFE.putLong(chars, address, REF_0);
+        UNSAFE.putLong(chars, address + 8, REF_1);
+        this.off = off + 8;
+        writeString(path);
+        off = this.off;
+        chars = this.chars;
         if (off == chars.length) {
             chars = grow(off + 1);
         }
@@ -1224,8 +1240,11 @@ class JSONWriterUTF16
         int charsLen = bytes.length * 2 + 3;
 
         int off = this.off;
-        ensureCapacity(off + charsLen + 2);
-        final char[] chars = this.chars;
+        char[] chars = this.chars;
+        int minCapacity = off + charsLen + 2;
+        if (minCapacity > chars.length) {
+            chars = grow(minCapacity);
+        }
         chars[off] = 'x';
         chars[off + 1] = '\'';
         off += 2;
@@ -1682,8 +1701,7 @@ class JSONWriterUTF16
         }
 
         putLong(chars, off, name);
-        chars[off + 8] = quote;
-        chars[off + 9] = ':';
+        putIntUnaligned(chars, off + 8, useSingleQuote ? QUOTE_COLON : QUOTE2_COLON);
         this.off = off + 10;
     }
 
@@ -1707,8 +1725,7 @@ class JSONWriterUTF16
 
         chars[off++] = quote;
         putLong(chars, off, name);
-        chars[off + 8] = quote;
-        chars[off + 9] = ':';
+        putIntUnaligned(chars, off + 8, useSingleQuote ? QUOTE_COLON : QUOTE2_COLON);
         this.off = off + 10;
     }
 
@@ -1864,8 +1881,7 @@ class JSONWriterUTF16
         }
 
         putLong(chars, off, name0, name1);
-        chars[off + 16] = quote;
-        chars[off + 17] = ':';
+        putIntUnaligned(chars, off + 16, useSingleQuote ? QUOTE_COLON : QUOTE2_COLON);
         this.off = off + 18;
     }
 
@@ -1889,8 +1905,7 @@ class JSONWriterUTF16
 
         chars[off++] = quote;
         putLong(chars, off, name0, name1);
-        chars[off + 16] = quote;
-        chars[off + 17] = ':';
+        putIntUnaligned(chars, off + 16, useSingleQuote ? QUOTE_COLON : QUOTE2_COLON);
         this.off = off + 18;
     }
 
@@ -2801,7 +2816,7 @@ class JSONWriterUTF16
 
         ZoneOffset offset = time.getOffset();
         int off = this.off;
-        int minCapacity = off + 25;
+        int minCapacity = off + 28;
         char[] chars = this.chars;
         if (minCapacity > chars.length) {
             chars = grow(minCapacity);
@@ -2926,11 +2941,8 @@ class JSONWriterUTF16
             }
         }
 
-        String str = new String(chars, 0, off);
-        if (charset == null) {
-            charset = StandardCharsets.UTF_8;
-        }
-        return str.getBytes(charset);
+        return new String(chars, 0, off)
+                .getBytes(charset != null ? charset : StandardCharsets.UTF_8);
     }
 
     @Override
@@ -2950,11 +2962,6 @@ class JSONWriterUTF16
             return;
         }
 
-        final long NONE_DIRECT_FEATURES = ReferenceDetection.mask
-                | PrettyFormat.mask
-                | NotWriteEmptyArray.mask
-                | NotWriteDefaultValue.mask;
-
         if ((context.features & NONE_DIRECT_FEATURES) != 0) {
             ObjectWriter objectWriter = context.getObjectWriter(map.getClass());
             objectWriter.write(this, map, null, null, 0);
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
index ae1c12023..7d1e25ea7 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
@@ -25,7 +25,8 @@ import static com.alibaba.fastjson2.util.TypeUtils.isInt64;
 
 class JSONWriterUTF8
         extends JSONWriter {
-    static final byte[] REF_PREF = "{\"$ref\":".getBytes(StandardCharsets.ISO_8859_1);
+    static final long REF;
+    static final short QUOTE2_COLON, QUOTE_COLON;
     static final short[] HEX256;
 
     static {
@@ -41,6 +42,12 @@ class JSONWriterUTF8
         }
 
         HEX256 = digits;
+
+        byte[] chars = {'{', '"', '$', 'r', 'e', 'f', '"', ':'};
+        REF = UNSAFE.getLong(chars, ARRAY_CHAR_BASE_OFFSET);
+        QUOTE2_COLON = UNSAFE.getShort(chars, ARRAY_CHAR_BASE_OFFSET + 6);
+        chars[6] = '\'';
+        QUOTE_COLON = UNSAFE.getShort(chars, ARRAY_CHAR_BASE_OFFSET + 6);
     }
 
     final CacheItem cacheItem;
@@ -70,12 +77,18 @@ class JSONWriterUTF8
     @Override
     public final void writeReference(String path) {
         this.lastReference = path;
-
-        writeRaw(REF_PREF);
-        writeString(path);
         int off = this.off;
+        byte[] bytes = this.bytes;
+        if (off + 8 > bytes.length) {
+            bytes = grow(off + 8);
+        }
+        UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, REF);
+        this.off = off + 8;
+        writeString(path);
+        off = this.off;
+        bytes = this.bytes;
         if (off == bytes.length) {
-            grow(off + 1);
+            bytes = grow(off + 1);
         }
         bytes[off] = '}';
         this.off = off + 1;
@@ -136,6 +149,7 @@ class JSONWriterUTF8
 
         int off = this.off;
         int minCapacity = off + charsLen + 2;
+        byte[] bytes = this.bytes;
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
         }
@@ -183,8 +197,8 @@ class JSONWriterUTF8
             return Arrays.copyOf(bytes, off);
         }
 
-        String str = toString();
-        return str.getBytes(charset);
+        return toString()
+                .getBytes(charset);
     }
 
     @Override
@@ -319,7 +333,7 @@ class JSONWriterUTF8
         // startArray();
         int off = this.off;
         if (off == bytes.length) {
-            grow(off + 1);
+            grow0(off + 1);
         }
         bytes[off] = '[';
         this.off = off + 1;
@@ -328,19 +342,19 @@ class JSONWriterUTF8
             if (i != 0) {
                 off = this.off;
                 if (off == bytes.length) {
-                    grow(off + 1);
+                    grow0(off + 1);
                 }
                 bytes[off] = ',';
                 this.off = off + 1;
             }
 
-            String str = list.get(i);
-            writeString(str);
+            writeString(
+                    list.get(i));
         }
 
         off = this.off;
         if (off == bytes.length) {
-            ensureCapacity(off + 1);
+            grow0(off + 1);
         }
         bytes[off] = ']';
         this.off = off + 1;
@@ -1826,8 +1840,7 @@ class JSONWriterUTF8
 
         bytes[off] = (byte) quote;
         UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off + 1, name);
-        bytes[off + 9] = (byte) quote;
-        bytes[off + 10] = ':';
+        UNSAFE.putShort(bytes, ARRAY_BYTE_BASE_OFFSET + off + 9, useSingleQuote ? QUOTE_COLON : QUOTE2_COLON);
         this.off = off + 11;
     }
 
@@ -1983,8 +1996,7 @@ class JSONWriterUTF8
 
         UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name0);
         UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off + 8, name1);
-        bytes[off + 16] = (byte) quote;
-        bytes[off + 17] = ':';
+        UNSAFE.putShort(bytes, ARRAY_BYTE_BASE_OFFSET + off + 16, useSingleQuote ? QUOTE_COLON : QUOTE2_COLON);
         this.off = off + 18;
     }
 
@@ -2008,8 +2020,7 @@ class JSONWriterUTF8
         bytes[off++] = (byte) quote;
         UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off, name0);
         UNSAFE.putLong(bytes, ARRAY_BYTE_BASE_OFFSET + off + 8, name1);
-        bytes[off + 16] = (byte) quote;
-        bytes[off + 17] = ':';
+        UNSAFE.putShort(bytes, ARRAY_BYTE_BASE_OFFSET + off + 16, useSingleQuote ? QUOTE_COLON : QUOTE2_COLON);
         this.off = off + 18;
     }
 
@@ -2063,11 +2074,16 @@ class JSONWriterUTF8
 
     final void ensureCapacity(int minCapacity) {
         if (minCapacity > bytes.length) {
-            grow(minCapacity);
+            grow0(minCapacity);
         }
     }
 
     private byte[] grow(int minCapacity) {
+        grow0(minCapacity);
+        return bytes;
+    }
+
+    private void grow0(int minCapacity) {
         int oldCapacity = bytes.length;
         int newCapacity = oldCapacity + (oldCapacity >> 1);
         if (newCapacity - minCapacity < 0) {
@@ -2078,7 +2094,7 @@ class JSONWriterUTF8
         }
 
         // minCapacity is usually close to size, so this is a win:
-        return bytes = Arrays.copyOf(bytes, newCapacity);
+        bytes = Arrays.copyOf(bytes, newCapacity);
     }
 
     public final void writeInt32(int[] values) {
@@ -2735,7 +2751,7 @@ class JSONWriterUTF8
         }
 
         int off = this.off;
-        int minCapacity = off + 45;
+        int minCapacity = off + 28;
         byte[] bytes = this.bytes;
         if (minCapacity > bytes.length) {
             bytes = grow(minCapacity);
@@ -2934,11 +2950,6 @@ class JSONWriterUTF8
             return;
         }
 
-        final long NONE_DIRECT_FEATURES = ReferenceDetection.mask
-                | PrettyFormat.mask
-                | NotWriteEmptyArray.mask
-                | NotWriteDefaultValue.mask;
-
         if ((context.features & NONE_DIRECT_FEATURES) != 0) {
             ObjectWriter objectWriter = context.getObjectWriter(map.getClass());
             objectWriter.write(this, map, null, null, 0);
diff --git a/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderImplObject.java b/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderImplObject.java
index 829f37a06..085070893 100644
--- a/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderImplObject.java
+++ b/core/src/main/java/com/alibaba/fastjson2/reader/ObjectReaderImplObject.java
@@ -289,6 +289,9 @@ public final class ObjectReaderImplObject
             case 'n':
                 value = jsonReader.readNullOrNewDate();
                 break;
+            case 'x':
+                value = jsonReader.readBinary();
+                break;
             case 'S':
                 if (jsonReader.nextIfSet()) {
                     HashSet<Object> set = new HashSet<>();
diff --git a/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java b/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java
index fe008767c..a886f5b4b 100644
--- a/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java
+++ b/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java
@@ -1408,15 +1408,19 @@ public class IOUtils {
     public static void putInt(char[] buf, int pos, int v) {
         UNSAFE.putInt(
                 buf,
-                ARRAY_CHAR_BASE_OFFSET + (pos << 1),
+                ARRAY_CHAR_BASE_OFFSET + ((long) pos << 1),
                 BIG_ENDIAN ? Integer.reverseBytes(v) : v
         );
     }
 
+    public static void putIntUnaligned(char[] buf, int pos, int v) {
+        UNSAFE.putInt(buf, ARRAY_CHAR_BASE_OFFSET + ((long) pos << 1), v);
+    }
+
     public static void putLong(char[] buf, int pos, long v) {
         UNSAFE.putLong(
                 buf,
-                ARRAY_CHAR_BASE_OFFSET + (pos << 1),
+                ARRAY_CHAR_BASE_OFFSET + ((long) pos << 1),
                 BIG_ENDIAN ? Long.reverseBytes(v) : v
         );
     }
diff --git a/pom.xml b/pom.xml
index d65b6c103..0a8354276 100644
--- a/pom.xml
+++ b/pom.xml
@@ -773,7 +773,7 @@
                 </plugin>
                 <plugin>
                     <artifactId>maven-site-plugin</artifactId>
-                    <version>3.20.0</version>
+                    <version>3.21.0</version>
                 </plugin>
                 <plugin>
                     <artifactId>maven-gpg-plugin</artifactId>


Test patch:
diff --git a/core/src/test/java/com/alibaba/fastjson2/JSONReaderJSONBTest.java b/core/src/test/java/com/alibaba/fastjson2/JSONReaderJSONBTest.java
index c309a08e3..9902df6da 100644
--- a/core/src/test/java/com/alibaba/fastjson2/JSONReaderJSONBTest.java
+++ b/core/src/test/java/com/alibaba/fastjson2/JSONReaderJSONBTest.java
@@ -388,4 +388,15 @@ public class JSONReaderJSONBTest {
         JSONReader jsonReader = JSONReader.ofJSONB(jsonBytes);
         jsonReader.reset(jsonReader.mark());
     }
+
+    @Test
+    public void unsupport() {
+        JSONReaderJSONB jsonReader = (JSONReaderJSONB) JSONReader.ofJSONB(JSONB.toBytes("abc"));
+        jsonReader.notSupportType(JSONB.Constants.BC_ARRAY);
+        assertThrows(JSONException.class, () -> jsonReader.notSupportString());
+        assertThrows(JSONException.class, () -> jsonReader.readInt32ValueError(JSONB.Constants.BC_ARRAY));
+        assertThrows(JSONException.class, () -> jsonReader.readInt64ValueError(JSONB.Constants.BC_ARRAY));
+        assertThrows(JSONException.class, () -> jsonReader.readStringError());
+        assertThrows(JSONException.class, () -> jsonReader.typeRefNotFound(-1));
+    }
 }
diff --git a/core/src/test/java/com/alibaba/fastjson2/JSONReaderJSONBTest2.java b/core/src/test/java/com/alibaba/fastjson2/JSONReaderJSONBTest2.java
index 7461682b3..7287e96d3 100644
--- a/core/src/test/java/com/alibaba/fastjson2/JSONReaderJSONBTest2.java
+++ b/core/src/test/java/com/alibaba/fastjson2/JSONReaderJSONBTest2.java
@@ -436,4 +436,49 @@ public class JSONReaderJSONBTest2 {
             }
         }
     }
+
+    @Test
+    public void readLength() {
+        StringBuilder buf = new StringBuilder(1024 * 1024);
+        int[] lengths = new int[10];
+        for (int i = 0, x = 1; i < lengths.length; i++, x *= 4) {
+            lengths[i] = x;
+        }
+        for (int length : lengths) {
+            for (int i = 0; i < length; i++) {
+                buf.append('0');
+            }
+            String str = buf.toString();
+            byte[] jsonBytes = JSONB.toBytes(str);
+            JSONReaderJSONB jsonReader = (JSONReaderJSONB) JSONReader.ofJSONB(jsonBytes);
+            if (jsonReader.nextIfMatch(JSONB.Constants.BC_STR_ASCII)) {
+                assertEquals(
+                        str.length(),
+                        jsonReader.readLength());
+            }
+            assertFalse(jsonReader.isArray());
+        }
+
+        for (int length : lengths) {
+            int[] array = new int[length];
+            byte[] jsonBytes = JSONB.toBytes(array);
+            JSONReaderJSONB jsonReader = (JSONReaderJSONB) JSONReader.ofJSONB(jsonBytes);
+            if (jsonReader.nextIfMatch(JSONB.Constants.BC_ARRAY)) {
+                assertEquals(
+                        length,
+                        jsonReader.readLength());
+            }
+        }
+
+        {
+            byte[] jsonBytes = JSONB.toBytes(1024 * 1024 * 512);
+            JSONReaderJSONB jsonReader = (JSONReaderJSONB) JSONReader.ofJSONB(jsonBytes);
+            assertThrows(JSONException.class, () -> jsonReader.readLength());
+        }
+        {
+            byte[] jsonBytes = JSONB.toBytes("xxx");
+            JSONReaderJSONB jsonReader = (JSONReaderJSONB) JSONReader.ofJSONB(jsonBytes);
+            assertThrows(JSONException.class, () -> jsonReader.readLength());
+        }
+    }
 }
diff --git a/core/src/test/java/com/alibaba/fastjson2/JSONWriterJSONBTest.java b/core/src/test/java/com/alibaba/fastjson2/JSONWriterJSONBTest.java
index f0b94de28..8212bc6f9 100644
--- a/core/src/test/java/com/alibaba/fastjson2/JSONWriterJSONBTest.java
+++ b/core/src/test/java/com/alibaba/fastjson2/JSONWriterJSONBTest.java
@@ -5,13 +5,15 @@ import com.alibaba.fastjson2.util.Fnv;
 import org.junit.jupiter.api.Test;
 
 import java.lang.reflect.Field;
+import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.nio.charset.StandardCharsets;
-import java.time.Instant;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
+import java.text.DecimalFormat;
+import java.time.*;
 import java.util.Arrays;
+import java.util.UUID;
 
+import static com.alibaba.fastjson2.JSONWriter.Feature.BrowserSecure;
 import static org.junit.jupiter.api.Assertions.*;
 
 public class JSONWriterJSONBTest {
@@ -454,4 +456,431 @@ public class JSONWriterJSONBTest {
         byte[] jsonbBytes = jsonWriter.getBytes();
         assertEquals(str, JSONB.parse(jsonbBytes));
     }
+
+    @Test
+    public void grow() {
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeNull();
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeReference("$.abc");
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeString(Arrays.asList("abc"));
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeStringLatin1(new byte[] {1, 2, 3});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB(BrowserSecure);
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeStringLatin1(new byte[] {1, '>', '<'});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB(BrowserSecure);
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeStringLatin1(new byte[] {'a', 'b', 'c'});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeString(new char[] {'a', 'b', 'c'});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeString(new char[] {'a', 'b', 'c'}, 0, 3);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeUUID(UUID.randomUUID());
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt32(123);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt8((byte) 123);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt8(new byte[]{1, 2, 3});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt16((short) 123);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt32(new int[] {1, 2, 3});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeListInt32(Arrays.asList(1, 2, null));
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt64(123L);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt64(new long[] {1, 2, 3});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeListInt64(Arrays.asList(1L, 2L, null));
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeFloat(123);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDouble(123L);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeNameRaw(new byte[] {'a', 'b', 'c'});
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateTime14(2014, 4, 5, 6, 7, 8);
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateTime19(2014, 4, 5, 6, 7, 8);
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeLocalDate(LocalDate.MIN);
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeLocalDateTime(LocalDateTime.MIN);
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateYYYMMDD8(2014, 4, 5);
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateYYYMMDD10(2014, 4, 5);
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeLocalTime(LocalTime.MIN);
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            ZonedDateTime now = ZonedDateTime.now();
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeZonedDateTime(now);
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            OffsetDateTime now = OffsetDateTime.now();
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeOffsetDateTime(now);
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            OffsetTime now = OffsetTime.now();
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeOffsetTime(now);
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeBigInt(new BigInteger("123456789012345678901234567890"), 0);
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDecimal(new BigDecimal("12345678901234567890.1234567890"), 0, new DecimalFormat("###.##"));
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.write(Arrays.asList(1));
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.write(Arrays.asList(1, 2));
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.write(Arrays.asList(1, 2, 3));
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeBool(true);
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.write(JSONObject.of());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray0();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray1();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray2();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray3();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray4();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray4();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray5();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray6();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray7();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray8();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray9();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray10();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray11();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray12();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray13();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray14();
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.startArray15();
+            }
+        }
+    }
+
+    @Test
+    public void println() {
+        JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+        jsonWriter.bytes = new byte[0];
+        jsonWriter.println();
+        assertEquals("<empty>", jsonWriter.toString());
+    }
+
+    @Test
+    public void unsupport() {
+        JSONWriter jsonWriter = JSONWriter.ofJSONB();
+        assertThrows(JSONException.class, () -> jsonWriter.writeRaw('a', 'b'));
+        JSONWriter.illegalYear(Integer.MAX_VALUE);
+    }
 }
diff --git a/core/src/test/java/com/alibaba/fastjson2/JSONWriterTest.java b/core/src/test/java/com/alibaba/fastjson2/JSONWriterTest.java
index 7e998b4a3..a6f345f89 100644
--- a/core/src/test/java/com/alibaba/fastjson2/JSONWriterTest.java
+++ b/core/src/test/java/com/alibaba/fastjson2/JSONWriterTest.java
@@ -2903,4 +2903,38 @@ public class JSONWriterTest {
             assertEquals("null", jsonWriter.toString());
         }
     }
+
+    @Test
+    public void startArrayN() {
+        JSONWriter jsonWriter = JSONWriter.of();
+        assertThrows(JSONException.class, () -> jsonWriter.startArray(0));
+        assertThrows(JSONException.class, () -> jsonWriter.startArray0());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray1());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray2());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray3());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray4());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray5());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray6());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray7());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray8());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray9());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray10());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray11());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray12());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray13());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray14());
+        assertThrows(JSONException.class, () -> jsonWriter.startArray15());
+    }
+
+    @Test
+    public void test() {
+        JSONWriter jsonWriter = JSONWriter.of();
+        assertFalse(jsonWriter.hasFilter());
+        assertFalse(jsonWriter.removeReference(new Object()));
+        assertEquals("$", jsonWriter.getPath(new Object()));
+        assertNull(jsonWriter.getPath());
+        jsonWriter.writeReference(new Object());
+        jsonWriter.setAttachment(new Object());
+        jsonWriter.getAttachment();
+    }
 }
diff --git a/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16Test.java b/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16Test.java
index 389776a07..b157d577a 100644
--- a/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16Test.java
+++ b/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16Test.java
@@ -6,11 +6,14 @@ import org.junit.jupiter.api.Test;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.nio.charset.StandardCharsets;
+import java.text.DecimalFormat;
+import java.time.*;
 import java.util.Arrays;
 import java.util.Date;
+import java.util.UUID;
 
-import static com.alibaba.fastjson2.JSONWriter.Feature.NullAsDefaultValue;
-import static com.alibaba.fastjson2.JSONWriter.Feature.PrettyFormat;
+import static com.alibaba.fastjson2.JSONWriter.Feature.*;
+import static com.alibaba.fastjson2.JSONWriter.Feature.BrowserSecure;
 import static com.alibaba.fastjson2.util.JDKUtils.*;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -743,4 +746,341 @@ public class JSONWriterUTF16Test {
             }
         }
     }
+
+    @Test
+    public void grow() {
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeNull();
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeReference("$.abc");
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeBase64(new byte[3]);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeString(Arrays.asList("abc"));
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeStringLatin1(new byte[] {1, 2, 3});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16(BrowserSecure);
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeStringLatin1(new byte[] {1, '>', '<'});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16(BrowserSecure);
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeStringLatin1(new byte[] {'a', 'b', 'c'});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeString(new char[] {'a', 'b', 'c'});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeString(new char[] {'a', 'b', 'c'}, 0, 3);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeUUID(UUID.randomUUID());
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt32(123);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt8((byte) 123);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt8(new byte[]{1, 2, 3});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt16((short) 123);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt32(new int[] {1, 2, 3});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeListInt32(Arrays.asList(1, 2, null));
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt64(123L);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt64(new long[] {1, 2, 3});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeListInt64(Arrays.asList(1L, 2L, null));
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeFloat(123);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDouble(123L);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeNameRaw(new char[] {'a', 'b', 'c'});
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeNameRaw(new char[] {'a', 'b', 'c'}, 0, 3);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeRaw(new char[] {'a', 'b', 'c'});
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeRaw('a', 'b');
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateTime14(2014, 4, 5, 6, 7, 8);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateTime19(2014, 4, 5, 6, 7, 8);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeLocalDate(LocalDate.MIN);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeLocalDateTime(LocalDateTime.MIN);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateYYYMMDD8(2014, 4, 5);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateYYYMMDD10(2014, 4, 5);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeTimeHHMMSS8(3, 4, 5);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeLocalTime(LocalTime.MIN);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            ZonedDateTime now = ZonedDateTime.now();
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeZonedDateTime(now);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            OffsetDateTime now = OffsetDateTime.now();
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeOffsetDateTime(now);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            OffsetTime now = OffsetTime.now();
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeOffsetTime(now);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            OffsetTime now = OffsetTime.now();
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateTimeISO8601(2014, 3, 4, 5, 6, 7, 8, 9, true);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeBigInt(new BigInteger("123456789012345678901234567890"), 0);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDecimal(new BigDecimal("12345678901234567890.1234567890"), 0, new DecimalFormat("###.##"));
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.write(Arrays.asList(1));
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.write(Arrays.asList(1, 2));
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.write(Arrays.asList(1, 2, 3));
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeBool(true);
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.write(JSONObject.of());
+            }
+        }
+    }
 }
diff --git a/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF8Test.java b/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF8Test.java
index cda2c0150..ce06dfb27 100644
--- a/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF8Test.java
+++ b/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF8Test.java
@@ -7,15 +7,11 @@ import org.junit.jupiter.api.Test;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.nio.charset.StandardCharsets;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.ZonedDateTime;
-import java.util.Arrays;
-import java.util.Date;
-
-import static com.alibaba.fastjson2.JSONWriter.Feature.NullAsDefaultValue;
-import static com.alibaba.fastjson2.JSONWriter.Feature.PrettyFormat;
+import java.text.DecimalFormat;
+import java.time.*;
+import java.util.*;
+
+import static com.alibaba.fastjson2.JSONWriter.Feature.*;
 import static com.alibaba.fastjson2.util.JDKUtils.ARRAY_CHAR_BASE_OFFSET;
 import static com.alibaba.fastjson2.util.JDKUtils.UNSAFE;
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -746,4 +742,365 @@ public class JSONWriterUTF8Test {
             jsonWriter.writeName16Raw(nameValue, 1);
         }
     }
+
+    @Test
+    public void writeInt32() {
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.writeInt32((Integer) null);
+            jsonWriter.writeComma();
+            jsonWriter.writeInt32((int[]) null);
+            jsonWriter.close();
+            assertEquals("null,null", jsonWriter.toString());
+        }
+    }
+
+    @Test
+    public void writeInt8() {
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.writeInt8(null);
+            jsonWriter.writeComma();
+            jsonWriter.writeInt8(new byte[]{1, 2, 3});
+            jsonWriter.close();
+            assertEquals("null,[1,2,3]", jsonWriter.toString());
+        }
+    }
+
+    @Test
+    public void grow() {
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeNull();
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeReference("$.abc");
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeBase64(new byte[3]);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeString(Arrays.asList("abc"));
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeStringLatin1(new byte[] {1, 2, 3});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8(BrowserSecure);
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeStringLatin1(new byte[] {1, '>', '<'});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8(BrowserSecure);
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeStringLatin1(new byte[] {'a', 'b', 'c'});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeString(new char[] {'a', 'b', 'c'});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeString(new char[] {'a', 'b', 'c'}, 0, 3);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeUUID(UUID.randomUUID());
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt32(123);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt8((byte) 123);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt8(new byte[]{1, 2, 3});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt16((short) 123);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt32(new int[] {1, 2, 3});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeListInt32(Arrays.asList(1, 2, null));
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt64(123L);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeInt64(new long[] {1, 2, 3});
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeListInt64(Arrays.asList(1L, 2L, null));
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeFloat(123);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDouble(123L);
+            }
+            jsonWriter.close();
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeNameRaw(new byte[] {'a', 'b', 'c'});
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeNameRaw(new byte[] {'a', 'b', 'c'}, 0, 3);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeRaw(new byte[] {'a', 'b', 'c'});
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeRaw('a', 'b');
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateTime14(2014, 4, 5, 6, 7, 8);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateTime19(2014, 4, 5, 6, 7, 8);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeLocalDate(LocalDate.MIN);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeLocalDateTime(LocalDateTime.MIN);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateYYYMMDD8(2014, 4, 5);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateYYYMMDD10(2014, 4, 5);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeTimeHHMMSS8(3, 4, 5);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeLocalTime(LocalTime.MIN);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            ZonedDateTime now = ZonedDateTime.now();
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeZonedDateTime(now);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            OffsetDateTime now = OffsetDateTime.now();
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeOffsetDateTime(now);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            OffsetTime now = OffsetTime.now();
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeOffsetTime(now);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            OffsetTime now = OffsetTime.now();
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDateTimeISO8601(2014, 3, 4, 5, 6, 7, 8, 9, true);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeBigInt(new BigInteger("123456789012345678901234567890"), 0);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeDecimal(new BigDecimal("12345678901234567890.1234567890"), 0, new DecimalFormat("###.##"));
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.write(Arrays.asList(1));
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.write(Arrays.asList(1, 2));
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.write(Arrays.asList(1, 2, 3));
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeBool(true);
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.write(JSONObject.of());
+            }
+        }
+    }
 }
diff --git a/core/src/test/java/com/alibaba/fastjson2/NameTest.java b/core/src/test/java/com/alibaba/fastjson2/NameTest.java
index f8adff77d..556f8b092 100644
--- a/core/src/test/java/com/alibaba/fastjson2/NameTest.java
+++ b/core/src/test/java/com/alibaba/fastjson2/NameTest.java
@@ -314,4 +314,466 @@ public class NameTest {
             }
         }
     }
+
+    @Test
+    public void growNameUTF8() {
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name1());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name2());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name3());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name4());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name5());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name6());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name7());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name8());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name9());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name10());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name11());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name12());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name13());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name14());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name15());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name16());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name17());
+            }
+        }
+        {
+            JSONWriterUTF8 jsonWriter = (JSONWriterUTF8) JSONWriter.ofUTF8();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name18());
+            }
+        }
+    }
+
+    @Test
+    public void growNameUTF16() {
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name1());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name2());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name3());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name4());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name5());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name6());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name7());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name8());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name9());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name10());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name11());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name12());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name13());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name14());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name15());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name16());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name17());
+            }
+        }
+        {
+            JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+            jsonWriter.chars = new char[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name18());
+            }
+        }
+    }
+
+    @Test
+    public void growNameJSONB() {
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name1());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name2());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name3());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name4());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name5());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name6());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name7());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name8());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name9());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name10());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name11());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name12());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name13());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name14());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name15());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name16());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name17());
+            }
+        }
+        {
+            JSONWriterJSONB jsonWriter = (JSONWriterJSONB) JSONWriter.ofJSONB();
+            jsonWriter.bytes = new byte[0];
+            for (int i = 0; i < 1000; i++) {
+                jsonWriter.writeAny(new Name18());
+            }
+        }
+    }
+
+    public static class Name1 {
+        public int n;
+    }
+
+    public static class Name2 {
+        public int n1;
+    }
+
+    public static class Name3 {
+        public int n12;
+    }
+
+    public static class Name4 {
+        public int n123;
+    }
+
+    public static class Name5 {
+        public int n1234;
+    }
+
+    public static class Name6 {
+        public int n12345;
+    }
+
+    public static class Name7 {
+        public int n123456;
+    }
+
+    public static class Name8 {
+        public int n1234567;
+    }
+
+    public static class Name9 {
+        public int n12345678;
+    }
+
+    public static class Name10 {
+        public int n123456789;
+    }
+
+    public static class Name11 {
+        public int n1234567890;
+    }
+
+    public static class Name12 {
+        public int n12345678901;
+    }
+
+    public static class Name13 {
+        public int n123456789012;
+    }
+
+    public static class Name14 {
+        public int n1234567890123;
+    }
+
+    public static class Name15 {
+        public int n12345678901234;
+    }
+
+    public static class Name16 {
+        public int n123456789012345;
+    }
+
+    public static class Name17 {
+        public int n1234567890123456;
+    }
+
+    public static class Name18 {
+        public int n12345678901234567;
+    }
 }
diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3208.java b/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3208.java
index 4d6ad314c..812e9eda0 100644
--- a/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3208.java
+++ b/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3208.java
@@ -9,6 +9,8 @@ import org.junit.jupiter.api.Test;
 
 import java.util.Arrays;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
 public class Issue3208 {
     @Test
     public void testArray() {
@@ -24,4 +26,15 @@ public class Issue3208 {
         Object parsed = JSON.parse(new String(jsonBytes));
         Assertions.assertNotNull(parsed);
     }
+
+    @Test
+    public void test() {
+        byte[] data = new byte[3];
+        data[0] = 1;
+        data[1] = 2;
+        data[2] = 3;
+        // 老版本会将数据转成jsonString并放到redis里面
+        String jsonString = com.alibaba.fastjson.JSONObject.toJSONString(data, SerializerFeature.WriteClassName, SerializerFeature.NotWriteDefaultValue);
+        assertEquals("[1, 2, 3]", Arrays.toString((byte[]) com.alibaba.fastjson2.JSON.parse(jsonString)));
+    }
 }
diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3214.java b/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3214.java
new file mode 100644
index 000000000..4b1f58dca
--- /dev/null
+++ b/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3214.java
@@ -0,0 +1,43 @@
+package com.alibaba.fastjson2.issues_3200;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONFactory;
+import com.alibaba.fastjson2.JSONObject;
+import com.alibaba.fastjson2.JSONReader;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class Issue3214 {
+    @Test
+    public void test() {
+        String json = "{\n"
+                + "  \"k1\":{\n"
+                + "    \"k2\":[\n"
+                + "      {\n"
+                + "        {} : {}\n"
+                + "      }\n"
+                + "    ]\n"
+                + "  }\n"
+                + "}";
+        JSONObject jsonObject = JSON.parseObject(json);
+        assertNotNull(jsonObject);
+    }
+
+    @Test
+    public void test1() {
+        JSONReader.Context context = JSONFactory.createReadContext();
+        context.setObjectSupplier(() -> new com.alibaba.fastjson.JSONObject());
+        String json = "{\n"
+                + "  \"k1\":{\n"
+                + "    \"k2\":[\n"
+                + "      {\n"
+                + "        {} : {}\n"
+                + "      }\n"
+                + "    ]\n"
+                + "  }\n"
+                + "}";
+        com.alibaba.fastjson.JSONObject jsonObject = (com.alibaba.fastjson.JSONObject) JSON.parse(json, context);
+        assertNotNull(jsonObject);
+    }
+}
diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3219.java b/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3219.java
new file mode 100644
index 000000000..830e3bfa7
--- /dev/null
+++ b/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3219.java
@@ -0,0 +1,27 @@
+package com.alibaba.fastjson2.issues_3200;
+
+import com.alibaba.fastjson2.JSON;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import static com.alibaba.fastjson2.JSONWriter.Feature.ReferenceDetection;
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+public class Issue3219 {
+    @Test
+    public void test() {
+        Map<String, Object> innerMap = new HashMap<>();
+        innerMap.put("xxx", "xxxx");
+        innerMap.put("ttt", "tttt");
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put("key1~", innerMap);
+        map.put("key2", innerMap);
+
+        String josnStr1 = JSON.toJSONString(map, ReferenceDetection);
+        Map map2 = JSON.parseObject(josnStr1, Map.class);
+        assertSame(map2.get("key2"), map2.get("key1~"));
+    }
+}
diff --git a/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3223.java b/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3223.java
new file mode 100644
index 000000000..5050d6a5f
--- /dev/null
+++ b/core/src/test/java/com/alibaba/fastjson2/issues_3200/Issue3223.java
@@ -0,0 +1,29 @@
+package com.alibaba.fastjson2.issues_3200;
+
+import com.alibaba.fastjson2.JSON;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class Issue3223 {
+    @Test
+    public void test() {
+        String res = "{\n" +
+                "    \"res\": \"Ñ\\n\"\n" +
+                "}";
+        ResBean resBean = JSON.parseObject(res, ResBean.class);
+        assertEquals("Ñ\n", resBean.res);
+    }
+
+    public static class ResBean {
+        private String res;
+
+        public String getRes() {
+            return res;
+        }
+
+        public void setRes(String res) {
+            this.res = res;
+        }
+    }
+}
diff --git a/fastjson1-compatible/src/test/java/com/alibaba/fastjson/v2issues/Issue3214.java b/fastjson1-compatible/src/test/java/com/alibaba/fastjson/v2issues/Issue3214.java
new file mode 100644
index 000000000..74b571ca5
--- /dev/null
+++ b/fastjson1-compatible/src/test/java/com/alibaba/fastjson/v2issues/Issue3214.java
@@ -0,0 +1,24 @@
+package com.alibaba.fastjson.v2issues;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class Issue3214 {
+    @Test
+    public void test() {
+        String json = "{\n"
+                + "  \"k1\":{\n"
+                + "    \"k2\":[\n"
+                + "      {\n"
+                + "        {} : {}\n"
+                + "      }\n"
+                + "    ]\n"
+                + "  }\n"
+                + "}";
+        JSONObject jsonObject = JSON.parseObject(json);
+        assertNotNull(jsonObject);
+    }
+}