Repository: alibaba/fastjson2
Pull request #3275 (2025-01-13 12:06:36)

Refactor
减少重复代码，提升可维护性


Patch:
diff --git a/benchmark/src/main/java/com/alibaba/fastjson2/benchmark/jjb/ClientsWriteCNBytes.java b/benchmark/src/main/java/com/alibaba/fastjson2/benchmark/jjb/ClientsWriteCNBytes.java
new file mode 100644
index 000000000..a1c11b0de
--- /dev/null
+++ b/benchmark/src/main/java/com/alibaba/fastjson2/benchmark/jjb/ClientsWriteCNBytes.java
@@ -0,0 +1,99 @@
+package com.alibaba.fastjson2.benchmark.jjb;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONB;
+import com.alibaba.fastjson2.JSONReader;
+import com.alibaba.fastjson2.JSONWriter;
+import com.dslplatform.json.DslJson;
+import com.dslplatform.json.runtime.Settings;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.gson.Gson;
+import org.apache.commons.io.IOUtils;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.TimeUnit;
+
+public class ClientsWriteCNBytes {
+    static Clients clients;
+    static final ObjectMapper mapper = new ObjectMapper();
+    static final Gson gson = new Gson();
+    static final DslJson<Object> dslJson = new DslJson<>(Settings.withRuntime().includeServiceLoader());
+    static final ThreadLocal<ByteArrayOutputStream> bytesOutLocal = ThreadLocal.withInitial(() -> new ByteArrayOutputStream());
+
+    static {
+        try {
+            InputStream is = ClientsWriteCNBytes.class.getClassLoader().getResourceAsStream("data/jjb/client_cn.json");
+            String str = IOUtils.toString(is, "UTF-8");
+            clients = JSONReader.of(str)
+                    .read(Clients.class);
+        } catch (Throwable ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    @Benchmark
+    public void fastjson2(Blackhole bh) {
+        bh.consume(JSON.toJSONBytes(clients));
+    }
+
+    @Benchmark
+    public void wast(Blackhole bh) {
+        bh.consume(io.github.wycst.wast.json.JSON.toJsonBytes(clients));
+    }
+
+    public void jsonb(Blackhole bh) {
+        bh.consume(JSONB.toBytes(clients));
+    }
+
+    public void jsonb_beanToArray(Blackhole bh) {
+        bh.consume(JSONB.toBytes(clients, JSONWriter.Feature.BeanToArray, JSONWriter.Feature.FieldBased));
+    }
+
+    public void fastjson2_str(Blackhole bh) {
+        bh.consume(JSON.toJSONString(clients));
+    }
+
+    @Benchmark
+    public void dsljson(Blackhole bh) throws IOException {
+        ByteArrayOutputStream bytesOut = bytesOutLocal.get();
+        bytesOut.reset();
+        dslJson.serialize(clients, bytesOut);
+        byte[] bytes = bytesOut.toByteArray();
+        bh.consume(bytes);
+    }
+
+//    @Benchmark
+    public void jackson(Blackhole bh) throws Exception {
+        bh.consume(mapper.writeValueAsBytes(clients));
+    }
+
+//    @Benchmark
+    public void gson(Blackhole bh) throws Exception {
+        bh.consume(gson
+                .toJson(clients)
+                .getBytes(StandardCharsets.UTF_8)
+        );
+    }
+
+    public static void main(String[] args) throws RunnerException {
+        Options options = new OptionsBuilder()
+                .include(ClientsWriteCNBytes.class.getName())
+                .mode(Mode.Throughput)
+                .timeUnit(TimeUnit.MILLISECONDS)
+                .warmupIterations(3)
+                .forks(2)
+                .threads(16)
+                .build();
+        new Runner(options).run();
+    }
+}
diff --git a/benchmark/src/main/resources/data/jjb/client_cn.json b/benchmark/src/main/resources/data/jjb/client_cn.json
new file mode 100644
index 000000000..b89dce797
--- /dev/null
+++ b/benchmark/src/main/resources/data/jjb/client_cn.json
@@ -0,0 +1,1 @@
+{"clients":[{"about":"中文yH1fix9pXbKEh5fJuly1","address":"中文Nljq0lukStDonHEcVRHE","age":64,"balance":0.44240027590133413,"company":"中文FgeVau3mS5w9mhcWwuKS","emails":["MfNsDmpsUsXpnDzvrcKm","jAyzPlasKbeYAvTdClOi","FODRICnLkoeXkifYBDZW","AIGvokIjTNJjgRQlcGAG","HvwnRvNkYdlVCrbBBZkD","EoaXVUulXKvnguaSuqrz","MjTFZwEgvEbGexOLOUCe","VFXuEiWfszLdGjWpVyXY"],"eyeColor":"BLUE","gender":"MrJ369tihTC7lZNK5bPo","guid":"70a95e90-425e-f2a7-db42-b83c18442df3","id":5917278237879270907,"index":500779379,"isActive":true,"latitude":3.237861088027525,"longitude":28.303947340611323,"name":"pVwnJvTLvrlferKSaG9o","partners":[{"id":-4992443277785453447,"name":"QvqPmFvFeLNggovkrLJLTHMehPHXFv","since":"1917-12-23T06:56:19.5013299Z"},{"id":7414865681841083540,"name":"lomuqksUvvBkkdyOUOfYVDopkTQGMK","since":"1983-12-24T09:34:01.284158669Z"},{"id":8483963072105131018,"name":"LOcRXNwppbCbrKtbnZlEFDFoNaHfAm","since":"1973-06-09T03:42:43.661968037Z"},{"id":-2059367369353171635,"name":"KQZVaVAxxaagquXdlVqaEbirVREPrc","since":"1914-04-26T17:12:57.205244091Z"},{"id":216128505382995309,"name":"bQpPRcRPsmnXSUApCtLoeIoWLFcylD","since":"1925-03-25T00:02:16.950150228Z"},{"id":-6331778364589206153,"name":"TpRJOziKUAgGJlbeleTcHwDgagmits","since":"1987-09-13T01:20:47.997888071Z"},{"id":-3449909979167971348,"name":"wCAsmHghlJNNONapFCDDiDDsixNKTu","since":"1982-10-25T04:05:34.720262937Z"},{"id":-5177986292895188953,"name":"dYhtDCbappBRjNHmUZOFpNyeglbwiw","since":"1919-10-14T10:28:31.669682461Z"},{"id":6239205551293135613,"name":"qUmJvesyiWMIZzBNLIOCjGkLaUMavd","since":"1940-10-14T04:47:37.631870618Z"},{"id":8851381720745793026,"name":"RsYbNUldwNFbAkxIYlemjptpecueDz","since":"1923-03-01T03:26:34.449016475Z"}],"phones":[1554466975,1263898911],"picture":"pVJdkPiSIno4Lr4n6T48xftyqIVnbuOWFkISpRY5gJAS0HDGfNM4Xs5Aw7L0yMS9Pu39coV6V6M11MXspNSMLoBO17CU4pmnrP4X","registered":"1930-06-24","tags":["1LGhuAhMHT","d2CMWFnmKs","I5Kz2sl3ea","nEjMMcLHOG","Wf5vWHhffW","3o5XjSt8bK","403BW3jTeF","Yqo14HhTmq","tOK5V9eaM3","EEFvDelYvP","LAmXdWfKw7","5xZCukg63f","muqvClzcXO","HEVG0HHKXn","5EdKtQZX6D","nVNmXvckwP","5d940ocGOK","7EUFIBtKW0","TGL1fImxEw","K9TnndP7Or","aA8GoXyO7W","a3RMQL8a51","7Y7RyeHXVs"]}]}
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONBDump.java b/core/src/main/java/com/alibaba/fastjson2/JSONBDump.java
index 246e291e3..dc55003b8 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONBDump.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONBDump.java
@@ -1,5 +1,6 @@
 package com.alibaba.fastjson2;
 
+import com.alibaba.fastjson2.util.IOUtils;
 import com.alibaba.fastjson2.util.JDKUtils;
 
 import java.math.BigDecimal;
@@ -279,11 +280,9 @@ final class JSONBDump {
                         );
                         break;
                     case BC_INT64:
-                        long unscaledValueLong = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
                         unscaledValue = BigInteger.valueOf(
-                                BIG_ENDIAN
-                                        ? unscaledValueLong
-                                        : Long.reverseBytes(unscaledValueLong));
+                                IOUtils.getLongBE(bytes, offset)
+                        );
                         offset += 8;
                         break;
                     default:
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderJSONB.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderJSONB.java
index 706a1cbca..259e7018f 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderJSONB.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderJSONB.java
@@ -18,7 +18,7 @@ import static com.alibaba.fastjson2.JSONB.typeName;
 import static com.alibaba.fastjson2.JSONFactory.*;
 import static com.alibaba.fastjson2.JSONReaderUTF8.*;
 import static com.alibaba.fastjson2.util.DateUtils.*;
-import static com.alibaba.fastjson2.util.IOUtils.getLongBigEndian;
+import static com.alibaba.fastjson2.util.IOUtils.getLongBE;
 import static com.alibaba.fastjson2.util.JDKUtils.*;
 import static com.alibaba.fastjson2.util.TypeUtils.toBigDecimal;
 import static java.nio.charset.StandardCharsets.ISO_8859_1;
@@ -376,9 +376,8 @@ final class JSONReaderJSONB
                 } else if (valueType == BC_OBJECT) {
                     value = readObject();
                 } else if (valueType == BC_INT64) {
-                    long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset + 1);
+                    value = IOUtils.getLongBE(bytes, offset + 1);
                     offset += 9;
-                    value = BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value);
                 } else if (valueType >= BC_ARRAY_FIX_MIN && valueType <= BC_ARRAY) {
                     offset++;
                     int len;
@@ -562,9 +561,9 @@ final class JSONReaderJSONB
                 return (long) int32Value;
             }
             case BC_INT64: {
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value);
+                return int64Value;
             }
             case BC_BIGINT: {
                 int len = readInt32Value();
@@ -582,9 +581,9 @@ final class JSONReaderJSONB
                 return (float) readInt32Value();
             }
             case BC_DOUBLE: {
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return Double.longBitsToDouble(BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value));
+                return Double.longBitsToDouble(int64Value);
             }
             case BC_DOUBLE_LONG: {
                 return (double) readInt64Value();
@@ -728,9 +727,9 @@ final class JSONReaderJSONB
                 return Instant.ofEpochSecond(epochSeconds, nano);
             }
             case BC_TIMESTAMP_MILLIS: {
-                long millis = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long millis = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return new Date(BIG_ENDIAN ? millis : Long.reverseBytes(millis));
+                return new Date(millis);
             }
             case BC_BIGINT_LONG: {
                 return BigInteger.valueOf(
@@ -1075,9 +1074,8 @@ final class JSONReaderJSONB
                 value = readObject();
             } else if (valueType == BC_INT64) {
                 offset++;
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                value = BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value);
             } else if (valueType >= BC_ARRAY_FIX_MIN && valueType <= BC_ARRAY) {
                 offset++;
                 int len = valueType == BC_ARRAY
@@ -1136,9 +1134,8 @@ final class JSONReaderJSONB
                 offset += 3;
                 value = int3;
             } else if (valueType == BC_INT32) {
-                int int32Value = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset + 1);
+                value = IOUtils.getIntBE(bytes, offset + 1);
                 offset += 5;
-                value = BIG_ENDIAN ? int32Value : Integer.reverseBytes(int32Value);
             } else if (valueType == BC_REFERENCE) {
                 String reference = readReference();
                 if ("..".equals(reference)) {
@@ -3223,49 +3220,52 @@ final class JSONReaderJSONB
                 return "1.0";
             case BC_INT64_INT:
             case BC_INT32: {
-                int int32Value = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                int int32Value = IOUtils.getIntBE(bytes, offset);
                 offset += 4;
-                return Long.toString(BIG_ENDIAN ? int32Value : Integer.reverseBytes(int32Value));
+                return Long.toString(int32Value);
             }
             case BC_FLOAT_INT:
                 return Float.toString(
                         readInt32Value());
             case BC_FLOAT: {
-                int int32Value = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                int int32Value = IOUtils.getIntBE(bytes, offset);
                 offset += 4;
-                float floatValue = Float.intBitsToFloat(BIG_ENDIAN ? int32Value : Integer.reverseBytes(int32Value));
-                return Float.toString(floatValue);
+                return Float.toString(
+                        Float.intBitsToFloat(int32Value)
+                );
             }
             case BC_DOUBLE: {
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                double doubleValue = Double.longBitsToDouble(BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value));
-                return Double.toString(doubleValue);
+                return Double.toString(
+                        Double.longBitsToDouble(int64Value)
+                );
             }
             case BC_TIMESTAMP_SECONDS: {
-                int seconds = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long millis = IOUtils.getIntBE(bytes, offset) * 1000L;
                 offset += 4;
-                long millis = (BIG_ENDIAN ? seconds : Integer.reverseBytes(seconds)) * 1000L;
-                Date date = new Date(millis);
-                return DateUtils.toString(date);
+                return DateUtils.toString(
+                        new Date(millis)
+                );
             }
             case BC_TIMESTAMP_MINUTES: {
-                int minutes = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long millis = IOUtils.getIntBE(bytes, offset) * 60000L;
                 offset += 4;
-                long millis = (BIG_ENDIAN ? minutes : Integer.reverseBytes(minutes)) * 60000L;
-                Date date = new Date(millis);
-                return DateUtils.toString(date);
+                return DateUtils.toString(
+                        new Date(millis)
+                );
             }
             case BC_TIMESTAMP_MILLIS: {
-                long millis = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long millis = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                Date date = new Date(BIG_ENDIAN ? millis : Long.reverseBytes(millis));
-                return DateUtils.toString(date);
+                return DateUtils.toString(
+                        new Date(millis)
+                );
             }
             case BC_INT64:
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return Long.toString(BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value));
+                return Long.toString(int64Value);
             case BC_BIGINT: {
                 int len = readInt32Value();
                 byte[] bytes = new byte[len];
@@ -3416,14 +3416,10 @@ final class JSONReaderJSONB
                     + (bytes[offset + 1] & 0xFF);
             offset += 2;
         } else if (type == BC_INT64_INT) {
-            int int32Value = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
-            int64Value = BIG_ENDIAN ? int32Value : Integer.reverseBytes(int32Value);
+            int64Value = IOUtils.getIntBE(bytes, offset);
             offset += 4;
         } else if (type == BC_INT64) {
-            int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
-            if (!BIG_ENDIAN) {
-                int64Value = Long.reverseBytes(int64Value);
-            }
+            int64Value = IOUtils.getLongBE(bytes, offset);
             offset += 8;
         } else {
             this.offset = offset;
@@ -3471,14 +3467,14 @@ final class JSONReaderJSONB
                 offset += 2;
                 return int16Value;
             case BC_INT32: {
-                int int32Value = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                int int32Value = IOUtils.getIntBE(bytes, offset);
                 offset += 4;
-                return BIG_ENDIAN ? int32Value : Integer.reverseBytes(int32Value);
+                return int32Value;
             }
             case BC_FLOAT: {
-                int int32Value = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                int int32Value = IOUtils.getIntBE(bytes, offset);
                 offset += 4;
-                float floatValue = Float.intBitsToFloat(BIG_ENDIAN ? int32Value : Integer.reverseBytes(int32Value));
+                float floatValue = Float.intBitsToFloat(int32Value);
                 return (long) floatValue;
             }
             case BC_DOUBLE: {
@@ -3500,9 +3496,9 @@ final class JSONReaderJSONB
                 return seconds * 1000;
             }
             case BC_TIMESTAMP_MILLIS:
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value);
+                return int64Value;
             case BC_DECIMAL: {
                 int scale = readInt32Value();
                 BigInteger unscaledValue = readBigInteger();
@@ -3577,10 +3573,7 @@ final class JSONReaderJSONB
                     + (bytes[offset + 1] & 0xFF);
             offset += 2;
         } else if (type == BC_INT32) {
-            type = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
-            if (!BIG_ENDIAN) {
-                type = Integer.reverseBytes(type);
-            }
+            type = IOUtils.getIntBE(bytes, offset);
             offset += 4;
         } else {
             this.offset = offset;
@@ -3632,9 +3625,9 @@ final class JSONReaderJSONB
                 return (int) readInt64Value();
             }
             case BC_INT64: {
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return (int) (BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value));
+                return (int) int64Value;
             }
             case BC_FLOAT_INT:
                 return (int) (float) readInt32Value();
@@ -3754,10 +3747,7 @@ final class JSONReaderJSONB
                     + (bytes[offset + 1] & 0xFF);
             offset += 2;
         } else if (type == BC_INT32) {
-            int32Value = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
-            if (!BIG_ENDIAN) {
-                int32Value = Integer.reverseBytes(int32Value);
-            }
+            int32Value = IOUtils.getIntBE(bytes, offset);
             offset += 4;
         } else {
             this.offset = offset;
@@ -3791,14 +3781,10 @@ final class JSONReaderJSONB
                     + (bytes[offset + 1] & 0xFF);
             offset += 2;
         } else if (type == BC_INT64_INT) {
-            int int32Val = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
-            int64Value = BIG_ENDIAN ? int32Val : Integer.reverseBytes(int32Val);
+            int64Value = IOUtils.getIntBE(bytes, offset);
             offset += 4;
         } else if (type == BC_INT64) {
-            int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
-            if (!BIG_ENDIAN) {
-                int64Value = Long.reverseBytes(int64Value);
-            }
+            int64Value = IOUtils.getLongBE(bytes, offset);
             offset += 8;
         } else {
             this.offset = offset;
@@ -3851,9 +3837,9 @@ final class JSONReaderJSONB
         byte[] bytes = this.bytes;
         int offset = this.offset;
         if (bytes[offset] == BC_FLOAT) {
-            int int32Val = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset + 1);
+            int int32Val = IOUtils.getIntBE(bytes, offset + 1);
             this.offset = offset + 5;
-            return Float.intBitsToFloat(BIG_ENDIAN ? int32Val : Integer.reverseBytes(int32Val));
+            return Float.intBitsToFloat(int32Val);
         }
 
         return readFloat0();
@@ -3878,9 +3864,9 @@ final class JSONReaderJSONB
                 offset += 2;
                 return int16Value;
             case BC_INT64: {
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return (float) (BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value));
+                return (float) int64Value;
             }
             case BC_INT64_INT:
             case BC_INT32: {
@@ -3889,9 +3875,9 @@ final class JSONReaderJSONB
                 return int32Value;
             }
             case BC_DOUBLE: {
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return (float) Double.longBitsToDouble(BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value));
+                return (float) Double.longBitsToDouble(int64Value);
             }
             case BC_FLOAT_INT: {
                 return (float) readInt32Value();
@@ -4033,20 +4019,20 @@ final class JSONReaderJSONB
                 offset += 2;
                 return int16Value;
             case BC_INT64: {
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return (double) (BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value));
+                return (double) int64Value;
             }
             case BC_INT64_INT:
             case BC_INT32: {
-                int int32Value = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                int int32Value = IOUtils.getIntBE(bytes, offset);
                 offset += 4;
-                return BIG_ENDIAN ? int32Value : Integer.reverseBytes(int32Value);
+                return int32Value;
             }
             case BC_FLOAT:
-                int int32Value = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                int int32Value = IOUtils.getIntBE(bytes, offset);
                 offset += 4;
-                return Float.intBitsToFloat(BIG_ENDIAN ? int32Value : Integer.reverseBytes(int32Value));
+                return Float.intBitsToFloat(int32Value);
             case BC_FLOAT_INT: {
                 return (float) readInt32Value();
             }
@@ -4214,9 +4200,9 @@ final class JSONReaderJSONB
                 return (long) int32Value;
             }
             case BC_INT64: {
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value);
+                return int64Value;
             }
             case BC_BIGINT: {
                 int len = readInt32Value();
@@ -4239,9 +4225,9 @@ final class JSONReaderJSONB
                 return (float) readInt32Value();
             }
             case BC_DOUBLE:
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return Double.longBitsToDouble(BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value));
+                return Double.longBitsToDouble(int64Value);
             case BC_DOUBLE_LONG:
                 return (double) readInt64Value();
             case BC_DECIMAL: {
@@ -4301,12 +4287,9 @@ final class JSONReaderJSONB
                 decimal = BigDecimal.valueOf(getInt(bytes, offset + 1), scale);
                 offset += 5;
             } else if (bytes[offset] == BC_INT64) {
-                long unscaledValue = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset + 1);
                 decimal = BigDecimal.valueOf(
-                        BIG_ENDIAN
-                                ? unscaledValue
-                                : Long.reverseBytes(unscaledValue), scale
-                );
+                        IOUtils.getLongBE(bytes, offset + 1),
+                        scale);
                 offset += 9;
             } else {
                 BigInteger unscaledValue = readBigInteger();
@@ -4359,16 +4342,16 @@ final class JSONReaderJSONB
                 return BigDecimal.valueOf((long) floatValue);
             }
             case BC_DOUBLE: {
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                double doubleValue = Double.longBitsToDouble(BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value));
+                double doubleValue = Double.longBitsToDouble(int64Value);
                 return BigDecimal.valueOf(
                         (long) doubleValue);
             }
             case BC_INT64: {
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return BigDecimal.valueOf(BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value));
+                return BigDecimal.valueOf(int64Value);
             }
             case BC_BIGINT: {
                 BigInteger bigInt = readBigInteger();
@@ -4500,16 +4483,16 @@ final class JSONReaderJSONB
                         (long) floatValue);
             }
             case BC_DOUBLE: {
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                double doubleValue = Double.longBitsToDouble(BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value));
+                double doubleValue = Double.longBitsToDouble(int64Value);
                 return BigInteger.valueOf(
                         (long) doubleValue);
             }
             case BC_INT64: {
-                long int64Value = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long int64Value = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return BigInteger.valueOf(BIG_ENDIAN ? int64Value : Long.reverseBytes(int64Value));
+                return BigInteger.valueOf(int64Value);
             }
             case BC_BINARY: {
                 int len = readInt32Value();
@@ -4936,9 +4919,9 @@ final class JSONReaderJSONB
             }
             case BC_INT64:
             case BC_TIMESTAMP_MILLIS: {
-                long millis = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long millis = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                return Instant.ofEpochMilli(BIG_ENDIAN ? millis : Long.reverseBytes(millis));
+                return Instant.ofEpochMilli(millis);
             }
             default:
                 break;
@@ -5036,9 +5019,9 @@ final class JSONReaderJSONB
             }
             case BC_INT64:
             case BC_TIMESTAMP_MILLIS: {
-                long millis = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
+                long millis = IOUtils.getLongBE(bytes, offset);
                 offset += 8;
-                Instant instant = Instant.ofEpochMilli(BIG_ENDIAN ? millis : Long.reverseBytes(millis));
+                Instant instant = Instant.ofEpochMilli(millis);
                 return ZonedDateTime.ofInstant(instant, DEFAULT_ZONE_ID);
             }
             default:
@@ -5065,8 +5048,8 @@ final class JSONReaderJSONB
                     throw new JSONException("uuid not support " + len);
                 }
                 uuid = new UUID(
-                        getLongBigEndian(bytes, offset),
-                        getLongBigEndian(bytes, offset + 8));
+                        getLongBE(bytes, offset),
+                        getLongBE(bytes, offset + 8));
                 offset += 16;
                 break;
             case BC_STR_ASCII_FIX_32: {
@@ -5327,9 +5310,9 @@ final class JSONReaderJSONB
                         null);
                 break;
             case BC_TIMESTAMP_MILLIS: {
-                long millis = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset + 1);
+                long millis = IOUtils.getLongBE(bytes, offset + 1);
                 this.offset += 9;
-                return new Date(BIG_ENDIAN ? millis : Long.reverseBytes(millis));
+                return new Date(millis);
             }
             case BC_TIMESTAMP_MINUTES: {
                 long minutes = getInt(bytes, offset + 1);
@@ -6303,7 +6286,6 @@ final class JSONReaderJSONB
     }
 
     static int getInt(byte[] bytes, int offset) {
-        int int32Value = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
-        return BIG_ENDIAN ? int32Value : Integer.reverseBytes(int32Value);
+        return IOUtils.getIntBE(bytes, offset);
     }
 }
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java
index cc2b97440..9c81a0060 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java
@@ -5162,7 +5162,7 @@ class JSONReaderUTF16
     }
 
     static int getInt(char[] chars, int offset) {
-        long int64Val = UNSAFE.getLong(chars, ARRAY_CHAR_BASE_OFFSET + (offset << 1));
+        long int64Val = IOUtils.getLongUnaligned(chars, offset);
 
         if ((int64Val & CHAR_MASK) != 0) {
             return 0;
@@ -5187,9 +5187,8 @@ class JSONReaderUTF16
     }
 
     static long getLong(char[] chars, int offset) {
-        long arrayOffset = ARRAY_CHAR_BASE_OFFSET + (offset << 1);
-        long int64Val0 = UNSAFE.getLong(chars, arrayOffset);
-        long int64Val1 = UNSAFE.getLong(chars, arrayOffset + 8);
+        long int64Val0 = IOUtils.getLongUnaligned(chars, offset);
+        long int64Val1 = IOUtils.getLongUnaligned(chars, offset + 4);
 
         if (((int64Val0 | int64Val1) & CHAR_MASK) != 0) {
             return 0;
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java
index 45a8857ac..17d209a9f 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java
@@ -6673,7 +6673,7 @@ class JSONReaderUTF8
     }
 
     static long parse4Nibbles(byte[] bytes, int offset) {
-        int x = getIntLittleEndian(bytes, offset);
+        int x = getIntLE(bytes, offset);
         byte[] ns = NIBBLES;
         return ns[x & 0xFF] << 12 | ns[(x >> 8) & 0xFF] << 8 | ns[(x >> 16) & 0xFF] << 4 | ns[(x >> 24) & 0xFF];
     }
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
index ce9408987..b1f8f2a81 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
@@ -29,7 +29,6 @@ import static com.alibaba.fastjson2.util.TypeUtils.isJavaScriptSupport;
 public abstract class JSONWriter
         implements Closeable {
     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;
 
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java
index 7045af4b3..e46127a68 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterJSONB.java
@@ -559,10 +559,10 @@ final class JSONWriterJSONB
 
         bytes[off] = BC_STR_ASCII;
         bytes[off + 1] = BC_INT32;
-        UNSAFE.putInt(
+        IOUtils.putIntBE(
                 bytes,
-                ARRAY_BYTE_BASE_OFFSET + off + 2,
-                BIG_ENDIAN ? strlen : Integer.reverseBytes(strlen)
+                off + 2,
+                strlen
         );
         return 6;
     }
@@ -1170,10 +1170,10 @@ final class JSONWriterJSONB
                 int secondsInt = (int) seconds;
 
                 bytes[off] = BC_TIMESTAMP_SECONDS;
-                UNSAFE.putInt(
+                IOUtils.putIntBE(
                         bytes,
-                        ARRAY_BYTE_BASE_OFFSET + off + 1,
-                        BIG_ENDIAN ? secondsInt : Integer.reverseBytes(secondsInt)
+                        off + 1,
+                        secondsInt
                 );
                 this.off = off + 5;
                 return;
@@ -1184,10 +1184,10 @@ final class JSONWriterJSONB
                 if (minutes >= Integer.MIN_VALUE && minutes <= Integer.MAX_VALUE) {
                     int minutesInt = (int) minutes;
                     bytes[off] = BC_TIMESTAMP_MINUTES;
-                    UNSAFE.putInt(
+                    IOUtils.putIntBE(
                             bytes,
-                            ARRAY_BYTE_BASE_OFFSET + off + 1,
-                            BIG_ENDIAN ? minutesInt : Integer.reverseBytes(minutesInt)
+                            off + 1,
+                            minutesInt
                     );
                     this.off = off + 5;
                     return;
@@ -1196,10 +1196,10 @@ final class JSONWriterJSONB
         }
 
         bytes[off] = BC_TIMESTAMP_MILLIS;
-        UNSAFE.putLong(
+        IOUtils.putLongBE(
                 bytes,
-                ARRAY_BYTE_BASE_OFFSET + off + 1,
-                BIG_ENDIAN ? millis : Long.reverseBytes(millis)
+                off + 1,
+                millis
         );
         this.off = off + 9;
     }
@@ -1236,10 +1236,10 @@ final class JSONWriterJSONB
                 size = 3;
             } else if (val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE) {
                 bytes[off] = BC_INT64_INT;
-                UNSAFE.putInt(
+                IOUtils.putIntBE(
                         bytes,
-                        ARRAY_BYTE_BASE_OFFSET + off + 1,
-                        BIG_ENDIAN ? (int) val : Integer.reverseBytes((int) val)
+                        off + 1,
+                        (int) val
                 );
                 size = 5;
             } else {
@@ -1273,19 +1273,11 @@ final class JSONWriterJSONB
             size = 3;
         } else if (val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE) {
             bytes[off] = BC_INT64_INT;
-            UNSAFE.putInt(
-                    bytes,
-                    ARRAY_BYTE_BASE_OFFSET + off + 1,
-                    BIG_ENDIAN ? (int) val : Integer.reverseBytes((int) val)
-            );
+            IOUtils.putIntBE(bytes, off + 1, (int) val);
             size = 5;
         } else {
             bytes[off] = BC_INT64;
-            UNSAFE.putLong(
-                    bytes,
-                    ARRAY_BYTE_BASE_OFFSET + off + 1,
-                    BIG_ENDIAN ? val : Long.reverseBytes(val)
-            );
+            IOUtils.putLongBE(bytes, off + 1, val);
             size = 9;
         }
         this.off = off + size;
@@ -1337,21 +1329,13 @@ final class JSONWriterJSONB
 
             if (val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE) {
                 bytes[off] = BC_INT64_INT;
-                UNSAFE.putInt(
-                        bytes,
-                        ARRAY_BYTE_BASE_OFFSET + off + 1,
-                        BIG_ENDIAN ? (int) val : Integer.reverseBytes((int) val)
-                );
+                IOUtils.putIntBE(bytes, off + 1, (int) val);
                 off += 5;
                 continue;
             }
 
             bytes[off] = BC_INT64;
-            UNSAFE.putLong(
-                    bytes,
-                    ARRAY_BYTE_BASE_OFFSET + off + 1,
-                    BIG_ENDIAN ? val : Long.reverseBytes(val)
-            );
+            IOUtils.putLongBE(bytes, off + 1, val);
             off += 9;
         }
         this.off = off;
@@ -1415,11 +1399,7 @@ final class JSONWriterJSONB
     private static int writeInt64Large(byte[] bytes, int off, long val) {
         if (val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE) {
             bytes[off] = BC_INT64_INT;
-            UNSAFE.putInt(
-                    bytes,
-                    ARRAY_BYTE_BASE_OFFSET + off + 1,
-                    BIG_ENDIAN ? (int) val : Integer.reverseBytes((int) val)
-            );
+            IOUtils.putIntBE(bytes, off + 1, (int) val);
             return 5;
         }
 
@@ -1428,11 +1408,7 @@ final class JSONWriterJSONB
 
     private static int writeInt64Large8(byte[] bytes, int off, long val) {
         bytes[off] = BC_INT64;
-        UNSAFE.putLong(
-                bytes,
-                ARRAY_BYTE_BASE_OFFSET + off + 1,
-                BIG_ENDIAN ? val : Long.reverseBytes(val)
-        );
+        IOUtils.putLongBE(bytes, off + 1, val);
         return 9;
     }
 
@@ -1452,11 +1428,7 @@ final class JSONWriterJSONB
         } else {
             bytes[off] = BC_FLOAT;
             i = Float.floatToIntBits(value);
-            UNSAFE.putInt(
-                    bytes,
-                    ARRAY_BYTE_BASE_OFFSET + off + 1,
-                    BIG_ENDIAN ? i : Integer.reverseBytes(i)
-            );
+            IOUtils.putIntBE(bytes, off + 1, i);
             off += 5;
         }
         this.off = off;
@@ -1506,11 +1478,7 @@ final class JSONWriterJSONB
         }
         bytes[off] = BC_DOUBLE;
         long i = Double.doubleToLongBits(value);
-        UNSAFE.putLong(
-                bytes,
-                ARRAY_BYTE_BASE_OFFSET + off + 1,
-                BIG_ENDIAN ? i : Long.reverseBytes(i)
-        );
+        IOUtils.putLongBE(bytes, off + 1, i);
         this.off = off + 9;
     }
 
@@ -1585,11 +1553,7 @@ final class JSONWriterJSONB
             }
 
             bytes[off] = BC_INT32;
-            UNSAFE.putInt(
-                    bytes,
-                    ARRAY_BYTE_BASE_OFFSET + off + 1,
-                    BIG_ENDIAN ? val : Integer.reverseBytes(val)
-            );
+            IOUtils.putIntBE(bytes, off + 1, val);
             off += 5;
         }
         this.off = off;
@@ -1707,11 +1671,7 @@ final class JSONWriterJSONB
                 size = 3;
             } else {
                 bytes[off] = BC_INT32;
-                UNSAFE.putInt(
-                        bytes,
-                        ARRAY_BYTE_BASE_OFFSET + off + 1,
-                        BIG_ENDIAN ? val : Integer.reverseBytes(val)
-                );
+                IOUtils.putIntBE(bytes, off + 1, val);
                 size = 5;
             }
         }
@@ -1741,11 +1701,7 @@ final class JSONWriterJSONB
             size = 3;
         } else {
             bytes[off] = BC_INT32;
-            UNSAFE.putInt(
-                    bytes,
-                    ARRAY_BYTE_BASE_OFFSET + off + 1,
-                    BIG_ENDIAN ? val : Integer.reverseBytes(val)
-            );
+            IOUtils.putIntBE(bytes, off + 1, val);
             size = 5;
         }
         this.off += size;
@@ -1794,11 +1750,7 @@ final class JSONWriterJSONB
                 off += 3;
             } else {
                 bytes[off] = BC_INT32;
-                UNSAFE.putInt(
-                        bytes,
-                        ARRAY_BYTE_BASE_OFFSET + off + 1,
-                        BIG_ENDIAN ? val : Integer.reverseBytes(val)
-                );
+                IOUtils.putIntBE(bytes, off + 1, val);
                 off += 5;
             }
         }
@@ -1820,11 +1772,7 @@ final class JSONWriterJSONB
             return 3;
         } else {
             bytes[off] = BC_INT32;
-            UNSAFE.putInt(
-                    bytes,
-                    ARRAY_BYTE_BASE_OFFSET + off + 1,
-                    BIG_ENDIAN ? val : Integer.reverseBytes(val)
-            );
+            IOUtils.putIntBE(bytes, off + 1, val);
             return 5;
         }
     }
@@ -1844,19 +1792,11 @@ final class JSONWriterJSONB
             return 3;
         } else if (val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE) {
             bytes[off] = BC_INT64_INT;
-            UNSAFE.putInt(
-                    bytes,
-                    ARRAY_BYTE_BASE_OFFSET + off + 1,
-                    BIG_ENDIAN ? (int) val : Integer.reverseBytes((int) val)
-            );
+            IOUtils.putIntBE(bytes, off + 1, (int) val);
             return 5;
         } else {
             bytes[off] = BC_INT64;
-            UNSAFE.putLong(
-                    bytes,
-                    ARRAY_BYTE_BASE_OFFSET + off + 1,
-                    BIG_ENDIAN ? val : Long.reverseBytes(val)
-            );
+            IOUtils.putLongBE(bytes, off + 1, val);
             return 9;
         }
     }
@@ -2150,18 +2090,8 @@ final class JSONWriterJSONB
 
         bytes[off] = BC_BINARY;
         bytes[off + 1] = BC_INT32_NUM_16;
-        long msb = value.getMostSignificantBits();
-        UNSAFE.putLong(
-                bytes,
-                ARRAY_BYTE_BASE_OFFSET + off + 2,
-                BIG_ENDIAN ? msb : Long.reverseBytes(msb)
-        );
-        long lsb = value.getLeastSignificantBits();
-        UNSAFE.putLong(
-                bytes,
-                ARRAY_BYTE_BASE_OFFSET + off + 10,
-                BIG_ENDIAN ? lsb : Long.reverseBytes(lsb)
-        );
+        IOUtils.putLongBE(bytes, off + 2, value.getMostSignificantBits());
+        IOUtils.putLongBE(bytes, off + 10, value.getLeastSignificantBits());
         this.off = off + 18;
     }
 
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
index 49c44ab22..eb526bbd9 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF16.java
@@ -27,6 +27,9 @@ import static com.alibaba.fastjson2.util.TypeUtils.*;
 
 class JSONWriterUTF16
         extends JSONWriter {
+    static final long BYTE_VEC_64_SINGLE_QUOTE = 0x00270027_00270027L;
+    static final long BYTE_VEC_64_DOUBLE_QUOTE = 0x00220022_00220022L;
+
     static final long REF_0, REF_1;
     static final int QUOTE2_COLON, QUOTE_COLON;
     static final int[] HEX256;
@@ -278,13 +281,13 @@ class JSONWriterUTF16
         final long vecQuote = this.byteVectorQuote;
         final int upperBound = (value.length - i) & ~7;
         for (; i < upperBound; i += 8) {
-            long vec64 = getLongLittleEndian(value, i);
+            long vec64 = getLongLE(value, i);
             if (containsEscaped(vec64, vecQuote)) {
                 escape = true;
                 break;
             }
-            IOUtils.putLong(chars, off, expand(vec64));
-            IOUtils.putLong(chars, off + 4, expand(vec64 >>> 32));
+            IOUtils.putLongLE(chars, off, expand(vec64));
+            IOUtils.putLongLE(chars, off + 4, expand(vec64 >>> 32));
             off += 8;
         }
         if (!escape) {
@@ -350,8 +353,10 @@ class JSONWriterUTF16
             return;
         }
 
-        boolean browserSecure = (context.features & BrowserSecure.mask) != 0;
-        boolean escapeNoneAscii = (context.features & EscapeNoneAscii.mask) != 0;
+        if ((context.features & (BrowserSecure.mask | EscapeNoneAscii.mask)) != 0) {
+            writeStringUTF16BrowserSecure(value);
+            return;
+        }
 
         boolean escape = false;
         int off = this.off;
@@ -360,15 +365,80 @@ class JSONWriterUTF16
             grow(minCapacity);
         }
 
+        final long vecQuote = this.useSingleQuote ? BYTE_VEC_64_SINGLE_QUOTE : BYTE_VEC_64_DOUBLE_QUOTE;
         final char[] chars = this.chars;
         chars[off++] = quote;
+        int i = 0, char_len = value.length >> 1;
+
+        final int upperBound = (char_len - i) & ~3;
+        for (; i < upperBound; i += 4) {
+            long v = getLongLE(value, i << 1);
+            if (containsEscapedUTF16(v, vecQuote)) {
+                break;
+            }
+            IOUtils.putLongLE(chars, off, v);
+            off += 4;
+        }
+        for (; i < char_len;) {
+            char c = getChar(value, i++);
+            if (c == '\\' || c == quote || c < ' ') {
+                escape = true;
+                break;
+            }
+
+            chars[off++] = c;
+        }
+
+        if (!escape) {
+            chars[off] = quote;
+            this.off = off + 1;
+            return;
+        }
+
+        writeStringEscapeUTF16(value);
+    }
+
+    static boolean containsEscapedUTF16(long v, long quote) {
+        /*
+          for (int i = 0; i < 8; ++i) {
+            byte c = (byte) data;
+            if (c == quote || c == '\\' || c < ' ') {
+                return true;
+            }
+            data >>>= 8;
+          }
+          return false;
+         */
+        long x22 = v ^ quote; // " -> 0x22, ' -> 0x27
+        long x5c = v ^ 0x005C005C_005C005CL;
+
+        x22 = (x22 - 0x00010001_00010001L) & ~x22;
+        x5c = (x5c - 0x00010001_00010001L) & ~x5c;
+
+        return ((x22 | x5c | (0x007F007F_007F007FL - v + 0x00100010_00100010L) | v) & 0x00800080_00800080L) != 0;
+    }
+
+    final void writeStringUTF16BrowserSecure(byte[] value) {
+        boolean escapeNoneAscii = (context.features & EscapeNoneAscii.mask) != 0;
+
+        boolean escape = false;
+        int off = this.off;
+        int minCapacity = off + value.length + 2;
+        if (minCapacity >= chars.length) {
+            grow(minCapacity);
+        }
 
-        for (int i = 0; i < value.length; i += 2) {
-            char c = UNSAFE.getChar(value, (long) Unsafe.ARRAY_BYTE_BASE_OFFSET + i);
+        final char[] chars = this.chars;
+        chars[off++] = quote;
+        for (int i = 0, char_len = value.length >> 1; i < char_len; i++) {
+            char c = getChar(value, i);
             if (c == '\\'
                     || c == quote
                     || c < ' '
-                    || (browserSecure && (c == '<' || c == '>' || c == '(' || c == ')'))
+                    || c == '<'
+                    || c == '>'
+                    || c == '('
+                    || c == ')'
                     || (escapeNoneAscii && c > 0x007F)
             ) {
                 escape = true;
@@ -454,33 +524,12 @@ class JSONWriterUTF16
                     chars[off++] = ch;
                     break;
                 case '\\':
-                    chars[off] = '\\';
-                    chars[off + 1] = ch;
-                    off += 2;
-                    break;
                 case '\r':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'r';
-                    off += 2;
-                    break;
                 case '\n':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'n';
-                    off += 2;
-                    break;
                 case '\b':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'b';
-                    off += 2;
-                    break;
                 case '\f':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'f';
-                    off += 2;
-                    break;
                 case '\t':
-                    chars[off] = '\\';
-                    chars[off + 1] = 't';
+                    writeEscapedChar(chars, off, ch);
                     off += 2;
                     break;
                 case 0:
@@ -491,25 +540,9 @@ class JSONWriterUTF16
                 case 5:
                 case 6:
                 case 7:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '0';
-                    chars[off + 5] = (char) ('0' + (int) ch);
-                    off += 6;
-                    break;
                 case 11:
                 case 14:
                 case 15:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '0';
-                    chars[off + 5] = (char) ('a' + (ch - 10));
-                    off += 6;
-                    break;
                 case 16:
                 case 17:
                 case 18:
@@ -520,26 +553,13 @@ class JSONWriterUTF16
                 case 23:
                 case 24:
                 case 25:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '1';
-                    chars[off + 5] = (char) ('0' + (ch - 16));
-                    off += 6;
-                    break;
                 case 26:
                 case 27:
                 case 28:
                 case 29:
                 case 30:
                 case 31:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '1';
-                    chars[off + 5] = (char) ('a' + (ch - 26));
+                    writeU4Hex2(chars, off, ch);
                     off += 6;
                     break;
                 case '<':
@@ -547,12 +567,7 @@ class JSONWriterUTF16
                 case '(':
                 case ')':
                     if (browserSecure) {
-                        chars[off] = '\\';
-                        chars[off + 1] = 'u';
-                        chars[off + 2] = '0';
-                        chars[off + 3] = '0';
-                        chars[off + 4] = DIGITS[(ch >>> 4) & 15];
-                        chars[off + 5] = DIGITS[ch & 15];
+                        writeU4HexU(chars, off, ch);
                         off += 6;
                     } else {
                         chars[off++] = ch;
@@ -560,12 +575,7 @@ class JSONWriterUTF16
                     break;
                 default:
                     if (escapeNoneAscii && ch > 0x007F) {
-                        chars[off] = '\\';
-                        chars[off + 1] = 'u';
-                        chars[off + 2] = DIGITS[(ch >>> 12) & 15];
-                        chars[off + 3] = DIGITS[(ch >>> 8) & 15];
-                        chars[off + 4] = DIGITS[(ch >>> 4) & 15];
-                        chars[off + 5] = DIGITS[ch & 15];
+                        writeU4HexU(chars, off, ch);
                         off += 6;
                     } else {
                         chars[off++] = ch;
@@ -599,33 +609,12 @@ class JSONWriterUTF16
                     chars[off++] = ch;
                     break;
                 case '\\':
-                    chars[off] = '\\';
-                    chars[off + 1] = ch;
-                    off += 2;
-                    break;
                 case '\r':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'r';
-                    off += 2;
-                    break;
                 case '\n':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'n';
-                    off += 2;
-                    break;
                 case '\b':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'b';
-                    off += 2;
-                    break;
                 case '\f':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'f';
-                    off += 2;
-                    break;
                 case '\t':
-                    chars[off] = '\\';
-                    chars[off + 1] = 't';
+                    writeEscapedChar(chars, off, ch);
                     off += 2;
                     break;
                 case 0:
@@ -636,25 +625,9 @@ class JSONWriterUTF16
                 case 5:
                 case 6:
                 case 7:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '0';
-                    chars[off + 5] = (char) ('0' + (int) ch);
-                    off += 6;
-                    break;
                 case 11:
                 case 14:
                 case 15:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '0';
-                    chars[off + 5] = (char) ('a' + (ch - 10));
-                    off += 6;
-                    break;
                 case 16:
                 case 17:
                 case 18:
@@ -665,26 +638,13 @@ class JSONWriterUTF16
                 case 23:
                 case 24:
                 case 25:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '1';
-                    chars[off + 5] = (char) ('0' + (ch - 16));
-                    off += 6;
-                    break;
                 case 26:
                 case 27:
                 case 28:
                 case 29:
                 case 30:
                 case 31:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '1';
-                    chars[off + 5] = (char) ('a' + (ch - 26));
+                    writeU4Hex2(chars, off, ch);
                     off += 6;
                     break;
                 case '<':
@@ -692,12 +652,7 @@ class JSONWriterUTF16
                 case '(':
                 case ')':
                     if (browserSecure) {
-                        chars[off] = '\\';
-                        chars[off + 1] = 'u';
-                        chars[off + 2] = '0';
-                        chars[off + 3] = '0';
-                        chars[off + 4] = DIGITS[(ch >>> 4) & 15];
-                        chars[off + 5] = DIGITS[ch & 15];
+                        writeU4HexU(chars, off, ch);
                         off += 6;
                     } else {
                         chars[off++] = ch;
@@ -705,12 +660,7 @@ class JSONWriterUTF16
                     break;
                 default:
                     if (escapeNoneAscii && ch > 0x007F) {
-                        chars[off] = '\\';
-                        chars[off + 1] = 'u';
-                        chars[off + 2] = DIGITS[(ch >>> 12) & 15];
-                        chars[off + 3] = DIGITS[(ch >>> 8) & 15];
-                        chars[off + 4] = DIGITS[(ch >>> 4) & 15];
-                        chars[off + 5] = DIGITS[ch & 15];
+                        writeU4HexU(chars, off, ch);
                         off += 6;
                     } else {
                         chars[off++] = ch;
@@ -744,33 +694,12 @@ class JSONWriterUTF16
                     chars[off++] = ch;
                     break;
                 case '\\':
-                    chars[off] = '\\';
-                    chars[off + 1] = ch;
-                    off += 2;
-                    break;
                 case '\r':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'r';
-                    off += 2;
-                    break;
                 case '\n':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'n';
-                    off += 2;
-                    break;
                 case '\b':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'b';
-                    off += 2;
-                    break;
                 case '\f':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'f';
-                    off += 2;
-                    break;
                 case '\t':
-                    chars[off] = '\\';
-                    chars[off + 1] = 't';
+                    writeEscapedChar(chars, off, ch);
                     off += 2;
                     break;
                 case 0:
@@ -781,25 +710,9 @@ class JSONWriterUTF16
                 case 5:
                 case 6:
                 case 7:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '0';
-                    chars[off + 5] = (char) ('0' + (int) ch);
-                    off += 6;
-                    break;
                 case 11:
                 case 14:
                 case 15:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '0';
-                    chars[off + 5] = (char) ('a' + (ch - 10));
-                    off += 6;
-                    break;
                 case 16:
                 case 17:
                 case 18:
@@ -810,26 +723,13 @@ class JSONWriterUTF16
                 case 23:
                 case 24:
                 case 25:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '1';
-                    chars[off + 5] = (char) ('0' + (ch - 16));
-                    off += 6;
-                    break;
                 case 26:
                 case 27:
                 case 28:
                 case 29:
                 case 30:
                 case 31:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '1';
-                    chars[off + 5] = (char) ('a' + (ch - 26));
+                    writeU4Hex2(chars, off, ch);
                     off += 6;
                     break;
                 case '<':
@@ -837,12 +737,7 @@ class JSONWriterUTF16
                 case '(':
                 case ')':
                     if (browserSecure) {
-                        chars[off] = '\\';
-                        chars[off + 1] = 'u';
-                        chars[off + 2] = '0';
-                        chars[off + 3] = '0';
-                        chars[off + 4] = DIGITS[(ch >>> 4) & 15];
-                        chars[off + 5] = DIGITS[ch & 15];
+                        writeU4HexU(chars, off, ch);
                         off += 6;
                     } else {
                         chars[off++] = ch;
@@ -850,12 +745,7 @@ class JSONWriterUTF16
                     break;
                 default:
                     if (escapeNoneAscii && ch > 0x007F) {
-                        chars[off] = '\\';
-                        chars[off + 1] = 'u';
-                        chars[off + 2] = DIGITS[(ch >>> 12) & 15];
-                        chars[off + 3] = DIGITS[(ch >>> 8) & 15];
-                        chars[off + 4] = DIGITS[(ch >>> 4) & 15];
-                        chars[off + 5] = DIGITS[ch & 15];
+                        writeU4HexU(chars, off, ch);
                         off += 6;
                     } else {
                         chars[off++] = ch;
@@ -890,33 +780,12 @@ class JSONWriterUTF16
                     chars[off++] = ch;
                     break;
                 case '\\':
-                    chars[off] = '\\';
-                    chars[off + 1] = ch;
-                    off += 2;
-                    break;
                 case '\r':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'r';
-                    off += 2;
-                    break;
                 case '\n':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'n';
-                    off += 2;
-                    break;
                 case '\b':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'b';
-                    off += 2;
-                    break;
                 case '\f':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'f';
-                    off += 2;
-                    break;
                 case '\t':
-                    chars[off] = '\\';
-                    chars[off + 1] = 't';
+                    writeEscapedChar(chars, off, ch);
                     off += 2;
                     break;
                 case 0:
@@ -927,25 +796,9 @@ class JSONWriterUTF16
                 case 5:
                 case 6:
                 case 7:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '0';
-                    chars[off + 5] = (char) ('0' + (int) ch);
-                    off += 6;
-                    break;
                 case 11:
                 case 14:
                 case 15:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '0';
-                    chars[off + 5] = (char) ('a' + (ch - 10));
-                    off += 6;
-                    break;
                 case 16:
                 case 17:
                 case 18:
@@ -956,26 +809,13 @@ class JSONWriterUTF16
                 case 23:
                 case 24:
                 case 25:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '1';
-                    chars[off + 5] = (char) ('0' + (ch - 16));
-                    off += 6;
-                    break;
                 case 26:
                 case 27:
                 case 28:
                 case 29:
                 case 30:
                 case 31:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '1';
-                    chars[off + 5] = (char) ('a' + (ch - 26));
+                    writeU4Hex2(chars, off, ch);
                     off += 6;
                     break;
                 case '<':
@@ -983,12 +823,7 @@ class JSONWriterUTF16
                 case '(':
                 case ')':
                     if (browserSecure) {
-                        chars[off] = '\\';
-                        chars[off + 1] = 'u';
-                        chars[off + 2] = '0';
-                        chars[off + 3] = '0';
-                        chars[off + 4] = DIGITS[(ch >>> 4) & 15];
-                        chars[off + 5] = DIGITS[ch & 15];
+                        writeU4HexU(chars, off, ch);
                         off += 6;
                     } else {
                         chars[off++] = ch;
@@ -996,12 +831,7 @@ class JSONWriterUTF16
                     break;
                 default:
                     if (escapeNoneAscii && ch > 0x007F) {
-                        chars[off] = '\\';
-                        chars[off + 1] = 'u';
-                        chars[off + 2] = '0';
-                        chars[off + 3] = '0';
-                        chars[off + 4] = DIGITS[(ch >>> 4) & 15];
-                        chars[off + 5] = DIGITS[ch & 15];
+                        writeU4HexU(chars, off, ch);
                         off += 6;
                     } else {
                         chars[off++] = ch;
@@ -1046,33 +876,12 @@ class JSONWriterUTF16
                     chars[off++] = ch;
                     break;
                 case '\\':
-                    chars[off] = '\\';
-                    chars[off + 1] = ch;
-                    off += 2;
-                    break;
                 case '\r':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'r';
-                    off += 2;
-                    break;
                 case '\n':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'n';
-                    off += 2;
-                    break;
                 case '\b':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'b';
-                    off += 2;
-                    break;
                 case '\f':
-                    chars[off] = '\\';
-                    chars[off + 1] = 'f';
-                    off += 2;
-                    break;
                 case '\t':
-                    chars[off] = '\\';
-                    chars[off + 1] = 't';
+                    writeEscapedChar(chars, off, ch);
                     off += 2;
                     break;
                 case 0:
@@ -1083,25 +892,9 @@ class JSONWriterUTF16
                 case 5:
                 case 6:
                 case 7:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '0';
-                    chars[off + 5] = (char) ('0' + (int) ch);
-                    off += 6;
-                    break;
                 case 11:
                 case 14:
                 case 15:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '0';
-                    chars[off + 5] = (char) ('a' + (ch - 10));
-                    off += 6;
-                    break;
                 case 16:
                 case 17:
                 case 18:
@@ -1112,36 +905,18 @@ class JSONWriterUTF16
                 case 23:
                 case 24:
                 case 25:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '1';
-                    chars[off + 5] = (char) ('0' + (ch - 16));
-                    off += 6;
-                    break;
                 case 26:
                 case 27:
                 case 28:
                 case 29:
                 case 30:
                 case 31:
-                    chars[off] = '\\';
-                    chars[off + 1] = 'u';
-                    chars[off + 2] = '0';
-                    chars[off + 3] = '0';
-                    chars[off + 4] = '1';
-                    chars[off + 5] = (char) ('a' + (ch - 26));
+                    writeU4Hex2(chars, off, ch);
                     off += 6;
                     break;
                 default:
                     if (escapeNoneAscii && ch > 0x007F) {
-                        chars[off] = '\\';
-                        chars[off + 1] = 'u';
-                        chars[off + 2] = DIGITS[(ch >>> 12) & 15];
-                        chars[off + 3] = DIGITS[(ch >>> 8) & 15];
-                        chars[off + 4] = DIGITS[(ch >>> 4) & 15];
-                        chars[off + 5] = DIGITS[ch & 15];
+                        writeU4HexU(chars, off, ch);
                         off += 6;
                     } else {
                         chars[off++] = ch;
@@ -1455,33 +1230,12 @@ class JSONWriterUTF16
                 chars[off++] = ch;
                 break;
             case '\\':
-                chars[off] = '\\';
-                chars[off + 1] = ch;
-                off += 2;
-                break;
             case '\r':
-                chars[off] = '\\';
-                chars[off + 1] = 'r';
-                off += 2;
-                break;
             case '\n':
-                chars[off] = '\\';
-                chars[off + 1] = 'n';
-                off += 2;
-                break;
             case '\b':
-                chars[off] = '\\';
-                chars[off + 1] = 'b';
-                off += 2;
-                break;
             case '\f':
-                chars[off] = '\\';
-                chars[off + 1] = 'f';
-                off += 2;
-                break;
             case '\t':
-                chars[off] = '\\';
-                chars[off + 1] = 't';
+                writeEscapedChar(chars, off, ch);
                 off += 2;
                 break;
             case 0:
@@ -2641,7 +2395,7 @@ class JSONWriterUTF16
             final int rem1 = millis - div * 10;
 
             if (rem1 != 0) {
-                IOUtils.putLong(chars, off, (DIGITS_K_64[millis] & 0xffffffffffff0000L) | DOT_X0);
+                IOUtils.putLongLE(chars, off, (DIGITS_K_64[millis] & 0xffffffffffff0000L) | DOT_X0);
                 off += 4;
             } else {
                 chars[off++] = '.';
@@ -3305,4 +3059,46 @@ class JSONWriterUTF16
         }
         this.off = off;
     }
+
+    private static final int U2;
+    private static final long U4;
+    private static final int[] ESCAPED_CHARS;
+    static {
+        {
+            char[] bytes = "\\u00".toCharArray();
+            U2 = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET);
+            U4 = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET);
+        }
+        {
+            char[] mapping = new char[] {
+                    '\\', '\\',
+                    '\n', 'n',
+                    '\r', 'r',
+                    '\f', 'f',
+                    '\b', 'b',
+                    '\t', 't'
+            };
+            char[] buf = {'\\', '\0'};
+            int[] shorts = new int[128];
+            for (int i = 0; i < mapping.length; i += 2) {
+                buf[1] = mapping[i + 1];
+                shorts[mapping[i]] = IOUtils.getIntUnaligned(buf, 0);
+            }
+            ESCAPED_CHARS = shorts;
+        }
+    }
+
+    static void writeEscapedChar(char[] chars, int off, int c0) {
+        IOUtils.putIntUnaligned(chars, off, ESCAPED_CHARS[c0 & 0x7f]);
+    }
+
+    static void writeU4Hex2(char[] chars, int off, int c) {
+        IOUtils.putLongUnaligned(chars, off, U4);
+        IOUtils.putIntLE(chars, off + 4, utf16Hex2(c));
+    }
+
+    static void writeU4HexU(char[] chars, int off, int c) {
+        IOUtils.putIntUnaligned(chars, off, U2);
+        IOUtils.putLongLE(chars, off + 2, utf16Hex4U(c));
+    }
 }
diff --git a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
index 30e89c168..3134bf9b0 100644
--- a/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
+++ b/core/src/main/java/com/alibaba/fastjson2/JSONWriterUTF8.java
@@ -493,7 +493,7 @@ class JSONWriterUTF8
         int i = 0;
         final int upperBound = (value.length - i) & ~7;
         for (; i < upperBound; i += 8) {
-            if (containsEscaped(IOUtils.getLongLittleEndian(value, i), vecQuote)) {
+            if (containsEscaped(IOUtils.getLongLE(value, i), vecQuote)) {
                 break;
             }
         }
@@ -2638,7 +2638,7 @@ class JSONWriterUTF8
             final int rem1 = millis - div * 10;
 
             if (rem1 != 0) {
-                putInt(bytes, off, DIGITS_K_32[millis] & 0xffffff00 | '.');
+                putIntLE(bytes, off, DIGITS_K_32[millis] & 0xffffff00 | '.');
                 off += 4;
             } else {
                 bytes[off++] = '.';
@@ -3001,16 +3001,16 @@ class JSONWriterUTF8
     }
 
     static void writeEscapedChar(byte[] bytes, int off, int c0) {
-        putShort(bytes, off, ESCAPED_CHARS[c0 & 0x7f]);
+        IOUtils.putShortLE(bytes, off, ESCAPED_CHARS[c0 & 0x7f]);
     }
 
     static void writeU4Hex2(byte[] bytes, int off, int c) {
-        putIntUnaligned(bytes, off, U4);
-        putShortUnaligned(bytes, off + 4, hex2(c));
+        IOUtils.putIntUnaligned(bytes, off, U4);
+        IOUtils.putShortLE(bytes, off + 4, hex2(c));
     }
 
     static void writeU4HexU(byte[] bytes, int off, int c) {
-        putShortUnaligned(bytes, off, U2);
-        putIntUnaligned(bytes, off + 2, hex4U(c));
+        IOUtils.putShortUnaligned(bytes, off, U2);
+        IOUtils.putIntLE(bytes, off + 2, hex4U(c));
     }
 }
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 56672ce5e..84a224430 100644
--- a/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java
+++ b/core/src/main/java/com/alibaba/fastjson2/util/IOUtils.java
@@ -830,7 +830,7 @@ public class IOUtils {
         final int div2 = div / 1000;
         final int rem1 = nano - div * 1000;
 
-        putInt(bytes, off, DIGITS_K_32[div2] & 0xffffff00 | '.');
+        putIntLE(bytes, off, DIGITS_K_32[div2] & 0xffffff00 | '.');
         off += 4;
 
         int v;
@@ -853,7 +853,7 @@ public class IOUtils {
             return off + 1;
         }
 
-        putInt(bytes, off, DIGITS_K_32[rem1] & 0xffffff00 | (v >> 24));
+        putIntLE(bytes, off, DIGITS_K_32[rem1] & 0xffffff00 | (v >> 24));
         return off + 4;
     }
 
@@ -862,7 +862,7 @@ public class IOUtils {
         final int div2 = div / 1000;
         final int rem1 = nano - div * 1000;
 
-        putLong(chars, off, DIGITS_K_64[div2] & 0xffffffffffff0000L | DOT_X0);
+        putLongLE(chars, off, DIGITS_K_64[div2] & 0xffffffffffff0000L | DOT_X0);
         off += 4;
 
         long v;
@@ -885,7 +885,7 @@ public class IOUtils {
             return off + 1;
         }
 
-        putLong(chars, off, DIGITS_K_64[rem1] & 0xffffffffffff0000L | (v >> 48));
+        putLongLE(chars, off, DIGITS_K_64[rem1] & 0xffffffffffff0000L | (v >> 48));
         return off + 4;
     }
 
@@ -947,7 +947,7 @@ public class IOUtils {
             } else if (start == 1) {
                 buf[pos++] = (byte) (v2 >> 16);
             }
-            putInt(buf, pos, v1 & 0xffffff00 | (v2 >> 24));
+            putIntLE(buf, pos, v1 & 0xffffff00 | (v2 >> 24));
             return pos + 4;
         }
 
@@ -968,7 +968,7 @@ public class IOUtils {
             buf[pos] = (byte) (v3 >> 24);
             buf[pos + 1] = (byte) (v2 >> 8);
             buf[pos + 2] = (byte) (v2 >> 16);
-            putInt(buf, pos + 3, v1 & 0xffffff00 | (v2 >> 24));
+            putIntLE(buf, pos + 3, v1 & 0xffffff00 | (v2 >> 24));
             return pos + 7;
         }
         final int r3 = (int) (q2 - q3 * 1000);
@@ -986,8 +986,8 @@ public class IOUtils {
             }
             buf[pos] = (byte) (v4 >> 24);
             buf[pos + 1] = (byte) (v3 >> 8);
-            putInt(buf, pos + 2, ((v2 & 0x00ffff00) << 8) | (v3 >> 16));
-            putInt(buf, pos + 6, v1 & 0xffffff00 | (v2 >> 24));
+            putIntLE(buf, pos + 2, ((v2 & 0x00ffff00) << 8) | (v3 >> 16));
+            putIntLE(buf, pos + 6, v1 & 0xffffff00 | (v2 >> 24));
             return pos + 10;
         }
         final int r4 = (int) (q3 - q4 * 1000);
@@ -1004,10 +1004,10 @@ public class IOUtils {
             } else if (start == 1) {
                 buf[pos++] = (byte) (v5 >> 16);
             }
-            putInt(buf, pos, v4 & 0xffffff00 | (v5 >> 24));
+            putIntLE(buf, pos, v4 & 0xffffff00 | (v5 >> 24));
             buf[pos + 4] = (byte) (v3 >> 8);
-            putInt(buf, pos + 5, ((v2 & 0x00ffff00) << 8) | (v3 >> 16));
-            putInt(buf, pos + 9, v1 & 0xffffff00 | (v2 >> 24));
+            putIntLE(buf, pos + 5, ((v2 & 0x00ffff00) << 8) | (v3 >> 16));
+            putIntLE(buf, pos + 9, v1 & 0xffffff00 | (v2 >> 24));
             return pos + 13;
         }
         final int r5 = q4 - q5 * 1000;
@@ -1025,16 +1025,16 @@ public class IOUtils {
             }
             buf[pos++] = (byte) (v >> 24);
         } else {
-            putInt(buf, pos, DIGITS_K_32[q5 - q6 * 1000] & 0xffffff00 | (q6 + '0'));
+            putIntLE(buf, pos, DIGITS_K_32[q5 - q6 * 1000] & 0xffffff00 | (q6 + '0'));
             pos += 4;
         }
 
         buf[pos] = (byte) (v5 >> 8);
-        putInt(buf, pos + 1, ((v4 & 0x00ffff00) << 8) | (v5 >> 16));
-        putInt(buf, pos + 5, v3 & 0xffffff00 | (v4 >> 24));
+        putIntLE(buf, pos + 1, ((v4 & 0x00ffff00) << 8) | (v5 >> 16));
+        putIntLE(buf, pos + 5, v3 & 0xffffff00 | (v4 >> 24));
         buf[pos + 9] = (byte) (v2 >> 8);
         buf[pos + 10] = (byte) (v2 >> 16);
-        putInt(buf, pos + 11, v1 & 0xffffff00 | (v2 >> 24));
+        putIntLE(buf, pos + 11, v1 & 0xffffff00 | (v2 >> 24));
         return pos + 15;
     }
 
@@ -1057,7 +1057,7 @@ public class IOUtils {
             long v = DIGITS_K_64[(int) i];
             int start = (byte) v;
             if (start == 0) {
-                putInt(buf, pos, (int) (v >> 16));
+                putIntLE(buf, pos, (int) (v >> 16));
                 pos += 2;
             } else if (start == 1) {
                 buf[pos++] = (char) (v >> 32);
@@ -1073,12 +1073,12 @@ public class IOUtils {
             final long v2 = DIGITS_K_64[(int) q1];
             int start = (byte) v2;
             if (start == 0) {
-                putInt(buf, pos, (int) (v2 >> 16));
+                putIntLE(buf, pos, (int) (v2 >> 16));
                 pos += 2;
             } else if (start == 1) {
                 buf[pos++] = (char) (v2 >> 32);
             }
-            putLong(buf, pos, v1 & 0xffffffffffff0000L | (v2 >> 48));
+            putLongLE(buf, pos, v1 & 0xffffffffffff0000L | (v2 >> 48));
             return pos + 4;
         }
 
@@ -1090,14 +1090,14 @@ public class IOUtils {
             final long v3 = DIGITS_K_64[(int) q2];
             int start = (byte) v3;
             if (start == 0) {
-                putInt(buf, pos, (int) (v3 >> 16));
+                putIntLE(buf, pos, (int) (v3 >> 16));
                 pos += 2;
             } else if (start == 1) {
                 buf[pos++] = (char) (v3 >> 32);
             }
             buf[pos] = (char) (v3 >> 48);
-            putInt(buf, pos + 1, (int) (v2 >> 16));
-            putLong(buf, pos + 3, v1 & 0xffffffffffff0000L | (v2 >> 48));
+            putIntLE(buf, pos + 1, (int) (v2 >> 16));
+            putLongLE(buf, pos + 3, v1 & 0xffffffffffff0000L | (v2 >> 48));
             return pos + 7;
         }
         final int r3 = (int) (q2 - q3 * 1000);
@@ -1107,15 +1107,15 @@ public class IOUtils {
             final long v4 = DIGITS_K_64[(int) q3];
             final int start = (byte) v4;
             if (start == 0) {
-                putInt(buf, pos, (int) (v4 >> 16));
+                putIntLE(buf, pos, (int) (v4 >> 16));
                 pos += 2;
             } else if (start == 1) {
                 buf[pos++] = (char) (v4 >> 32);
             }
             buf[pos] = (char) (v4 >> 48);
             buf[pos + 1] = (char) (v3 >> 16);
-            putLong(buf, pos + 2, ((v2 & 0x0000ffffffff0000L) << 16) | (v3 >> 32));
-            putLong(buf, pos + 6, v1 & 0xffffffffffff0000L | (v2 >> 48));
+            putLongLE(buf, pos + 2, ((v2 & 0x0000ffffffff0000L) << 16) | (v3 >> 32));
+            putLongLE(buf, pos + 6, v1 & 0xffffffffffff0000L | (v2 >> 48));
             return pos + 10;
         }
         final int r4 = (int) (q3 - q4 * 1000);
@@ -1125,16 +1125,16 @@ public class IOUtils {
             final long v5 = DIGITS_K_64[q4];
             int start = (byte) v5;
             if (start == 0) {
-                putInt(buf, pos, (int) (v5 >> 16));
+                putIntLE(buf, pos, (int) (v5 >> 16));
                 pos += 2;
             } else if (start == 1) {
                 buf[pos++] = (char) (v5 >> 32);
             }
             buf[pos] = (char) (v5 >> 48);
-            putInt(buf, pos + 1, (int) (v4 >> 16));
-            putLong(buf, pos + 3, v3 & 0xffffffffffff0000L | (v4 >> 48));
-            putInt(buf, pos + 7, (int) (v2 >> 16));
-            putLong(buf, pos + 9, v1 & 0xffffffffffff0000L | (v2 >> 48));
+            putIntLE(buf, pos + 1, (int) (v4 >> 16));
+            putLongLE(buf, pos + 3, v3 & 0xffffffffffff0000L | (v4 >> 48));
+            putIntLE(buf, pos + 7, (int) (v2 >> 16));
+            putLongLE(buf, pos + 9, v1 & 0xffffffffffff0000L | (v2 >> 48));
             return pos + 13;
         }
         final int r5 = q4 - q5 * 1000;
@@ -1152,17 +1152,17 @@ public class IOUtils {
             }
             buf[pos++] = (char) (v >> 24);
         } else {
-            putLong(buf, pos, DIGITS_K_64[q5 - q6 * 1000]);
+            putLongLE(buf, pos, DIGITS_K_64[q5 - q6 * 1000]);
             buf[pos] = (char) (q6 + '0');
             pos += 4;
         }
 
-        putInt(buf, pos, (int) (v5 >> 16));
-        putLong(buf, pos + 2, v4 & 0xffffffffffff0000L | (v5 >> 48));
+        putIntLE(buf, pos, (int) (v5 >> 16));
+        putLongLE(buf, pos + 2, v4 & 0xffffffffffff0000L | (v5 >> 48));
 
         buf[pos + 6] = (char) (v3 >> 16);
-        putLong(buf, pos + 7, ((v2 & 0x0000ffffffff0000L) << 16) | (v3 >> 32));
-        putLong(buf, pos + 11, v1 & 0xffffffffffff0000L | (v2 >> 48));
+        putLongLE(buf, pos + 7, ((v2 & 0x0000ffffffff0000L) << 16) | (v3 >> 32));
+        putLongLE(buf, pos + 11, v1 & 0xffffffffffff0000L | (v2 >> 48));
         return pos + 15;
     }
 
@@ -1178,7 +1178,7 @@ public class IOUtils {
         int v = DIGITS_K_32[i];
         final int start = (byte) v;
         if (start == 0) {
-            putShort(buf, pos, (short) (v >> 8));
+            putShortLE(buf, pos, (short) (v >> 8));
             pos += 2;
         } else if (start == 1) {
             buf[pos++] = (byte) (v >> 16);
@@ -1199,7 +1199,7 @@ public class IOUtils {
         long v = DIGITS_K_64[i];
         final int start = (byte) v;
         if (start == 0) {
-            putInt(buf, pos, (int) (v >> 16));
+            putIntLE(buf, pos, (int) (v >> 16));
             pos += 2;
         } else if (start == 1) {
             buf[pos++] = (char) (v >> 32);
@@ -1221,7 +1221,7 @@ public class IOUtils {
             int v = DIGITS_K_32[i];
             final int start = (byte) v;
             if (start == 0) {
-                putShort(buf, pos, (short) (v >> 8));
+                putShortLE(buf, pos, (short) (v >> 8));
                 pos += 2;
             } else if (start == 1) {
                 buf[pos++] = (byte) (v >> 16);
@@ -1235,7 +1235,7 @@ public class IOUtils {
         if ((byte) v2 == 1) {
             buf[pos++] = (byte) (v2 >> 16);
         }
-        putInt(buf, pos, (DIGITS_K_32[i - q1 * 1000]) & 0xffffff00 | (v2 >> 24));
+        putIntLE(buf, pos, (DIGITS_K_32[i - q1 * 1000]) & 0xffffff00 | (v2 >> 24));
         return pos + 4;
     }
 
@@ -1252,7 +1252,7 @@ public class IOUtils {
             long v = DIGITS_K_64[i];
             final int start = (byte) v;
             if (start == 0) {
-                putInt(buf, pos, (int) (v >> 16));
+                putIntLE(buf, pos, (int) (v >> 16));
                 pos += 2;
             } else if (start == 1) {
                 buf[pos++] = (char) (v >> 32);
@@ -1266,7 +1266,7 @@ public class IOUtils {
         if ((byte) v2 == 1) {
             buf[pos++] = (char) (v2 >> 32);
         }
-        putLong(buf, pos, DIGITS_K_64[i - q1 * 1000] & 0xffffffffffff0000L | (v2 >> 48));
+        putLongLE(buf, pos, DIGITS_K_64[i - q1 * 1000] & 0xffffffffffff0000L | (v2 >> 48));
         return pos + 4;
     }
 
@@ -1287,7 +1287,7 @@ public class IOUtils {
             int v = DIGITS_K_32[i];
             final int start = (byte) v;
             if (start == 0) {
-                putShort(buf, pos, (short) (v >> 8));
+                putShortLE(buf, pos, (short) (v >> 8));
                 pos += 2;
             } else if (start == 1) {
                 buf[pos++] = (byte) (v >> 16);
@@ -1303,12 +1303,12 @@ public class IOUtils {
             final int v2 = DIGITS_K_32[q1];
             int start = (byte) v2;
             if (start == 0) {
-                putShort(buf, pos, (short) (v2 >> 8));
+                putShortLE(buf, pos, (short) (v2 >> 8));
                 pos += 2;
             } else if (start == 1) {
                 buf[pos++] = (byte) (v2 >> 16);
             }
-            putInt(buf, pos, v1 & 0xffffff00 | (v2 >> 24));
+            putIntLE(buf, pos, v1 & 0xffffff00 | (v2 >> 24));
             return pos + 4;
         }
         final int q2 = q1 / 1000;
@@ -1319,19 +1319,19 @@ public class IOUtils {
             int v = DIGITS_K_32[q2];
             final int start = (byte) v;
             if (start == 0) {
-                putShort(buf, pos, (short) (v >> 8));
+                putShortLE(buf, pos, (short) (v >> 8));
                 pos += 2;
             } else if (start == 1) {
                 buf[pos++] = (byte) (v >> 16);
             }
             buf[pos++] = (byte) (v >> 24);
         } else {
-            putInt(buf, pos, DIGITS_K_32[q2 - q3 * 1000] & 0xffffff00 | (q3 + '0'));
+            putIntLE(buf, pos, DIGITS_K_32[q2 - q3 * 1000] & 0xffffff00 | (q3 + '0'));
             pos += 4;
         }
 
-        putShort(buf, pos, (short) (v2 >> 8));
-        putInt(buf, pos + 2, v1 & 0xffffff00 | (v2 >> 24));
+        putShortLE(buf, pos, (short) (v2 >> 8));
+        putIntLE(buf, pos + 2, v1 & 0xffffff00 | (v2 >> 24));
         return pos + 6;
     }
 
@@ -1351,7 +1351,7 @@ public class IOUtils {
             long v = DIGITS_K_64[i];
             final int start = (byte) v;
             if (start == 0) {
-                putInt(buf, pos, (int) (v >> 16));
+                putIntLE(buf, pos, (int) (v >> 16));
                 pos += 2;
             } else if (start == 1) {
                 buf[pos++] = (char) (v >> 32);
@@ -1366,12 +1366,12 @@ public class IOUtils {
             final long v2 = DIGITS_K_64[q1];
             int start = (byte) v2;
             if (start == 0) {
-                putInt(buf, pos, (int) (v2 >> 16));
+                putIntLE(buf, pos, (int) (v2 >> 16));
                 pos += 2;
             } else if (start == 1) {
                 buf[pos++] = (char) (v2 >> 32);
             }
-            putLong(buf, pos, v1 & 0xffffffffffff0000L | (v2 >> 48));
+            putLongLE(buf, pos, v1 & 0xffffffffffff0000L | (v2 >> 48));
             return pos + 4;
         }
         final int q2 = q1 / 1000;
@@ -1382,27 +1382,23 @@ public class IOUtils {
             long v = DIGITS_K_64[q2];
             final int start = (byte) v;
             if (start == 0) {
-                putInt(buf, pos, (int) (v >> 16));
+                putIntLE(buf, pos, (int) (v >> 16));
                 pos += 2;
             } else if (start == 1) {
                 buf[pos++] = (char) (v >> 32);
             }
             buf[pos++] = (char) (v >> 48);
         } else {
-            putLong(buf, pos, DIGITS_K_64[q2 - q3 * 1000]);
+            putLongLE(buf, pos, DIGITS_K_64[q2 - q3 * 1000]);
             buf[pos] = (char) (q3 + '0');
             pos += 4;
         }
 
-        putInt(buf, pos, (int) (v2 >> 16));
-        putLong(buf, pos + 2, v1 & 0xffffffffffff0000L | (v2 >> 48));
+        putIntLE(buf, pos, (int) (v2 >> 16));
+        putLongLE(buf, pos + 2, v1 & 0xffffffffffff0000L | (v2 >> 48));
         return pos + 6;
     }
 
-    public static void putChar(char[] buf, int pos, char v) {
-        UNSAFE.putChar(buf, ARRAY_CHAR_BASE_OFFSET + ((long) pos << 1), v);
-    }
-
     public static char getChar(char[] buf, int pos) {
         return UNSAFE.getChar(buf, ARRAY_CHAR_BASE_OFFSET + ((long) pos << 1));
     }
@@ -1411,28 +1407,20 @@ public class IOUtils {
         return UNSAFE.getChar(str, ARRAY_CHAR_BASE_OFFSET + ((long) pos << 1));
     }
 
-    public static void putShort(byte[] buf, int pos, short v) {
-        UNSAFE.putShort(
-                buf,
-                ARRAY_BYTE_BASE_OFFSET + pos,
-                BIG_ENDIAN ? Short.reverseBytes(v) : v
-        );
+    public static void putShortLE(byte[] buf, int pos, short v) {
+        UNSAFE.putShort(buf, ARRAY_BYTE_BASE_OFFSET + pos, convEndian(false, v));
     }
 
-    public static void putInt(byte[] buf, int pos, int v) {
-        UNSAFE.putInt(
-                buf,
-                ARRAY_BYTE_BASE_OFFSET + pos,
-                BIG_ENDIAN ? Integer.reverseBytes(v) : v
-        );
+    public static void putIntBE(byte[] buf, int pos, int v) {
+        UNSAFE.putInt(buf, ARRAY_BYTE_BASE_OFFSET + pos, convEndian(true, v));
     }
 
-    public static void putInt(char[] buf, int pos, int v) {
-        UNSAFE.putInt(
-                buf,
-                ARRAY_CHAR_BASE_OFFSET + ((long) pos << 1),
-                BIG_ENDIAN ? Integer.reverseBytes(v) : v
-        );
+    public static void putIntLE(byte[] buf, int pos, int v) {
+        UNSAFE.putInt(buf, ARRAY_BYTE_BASE_OFFSET + pos, convEndian(false, v));
+    }
+
+    public static void putIntLE(char[] buf, int pos, int v) {
+        UNSAFE.putInt(buf, ARRAY_CHAR_BASE_OFFSET + ((long) pos << 1), convEndian(false, v));
     }
 
     public static void putShortUnaligned(byte[] buf, int pos, short v) {
@@ -1447,12 +1435,20 @@ public class IOUtils {
         UNSAFE.putInt(buf, ARRAY_CHAR_BASE_OFFSET + pos, v);
     }
 
-    public static void putLong(char[] buf, int pos, long v) {
-        UNSAFE.putLong(
-                buf,
-                ARRAY_CHAR_BASE_OFFSET + ((long) pos << 1),
-                BIG_ENDIAN ? Long.reverseBytes(v) : v
-        );
+    public static void putLongLE(char[] buf, int pos, long v) {
+        UNSAFE.putLong(buf, ARRAY_CHAR_BASE_OFFSET + ((long) pos << 1), convEndian(false, v));
+    }
+
+    public static void putLongUnaligned(char[] buf, int pos, long v) {
+        UNSAFE.putLong(buf, ARRAY_CHAR_BASE_OFFSET + ((long) pos << 1), v);
+    }
+
+    public static void putLongBE(byte[] buf, int pos, long v) {
+        UNSAFE.putLong(buf, ARRAY_CHAR_BASE_OFFSET + pos, convEndian(true, v));
+    }
+
+    public static void putLongLE(byte[] buf, int pos, long v) {
+        UNSAFE.putLong(buf, ARRAY_CHAR_BASE_OFFSET + pos, convEndian(false, v));
     }
 
     public static int digit4(char[] chars, int off) {
@@ -1468,7 +1464,7 @@ public class IOUtils {
 
     public static int digit4(byte[] bytes, int off) {
         return digit4(
-                getIntLittleEndian(bytes, off)
+                getIntLE(bytes, off)
         );
     }
 
@@ -1529,7 +1525,7 @@ public class IOUtils {
 
     public static int digit3(byte[] bytes, int off) {
         return digit3(
-                getShortLittleEndian(bytes, off)
+                getShortE(bytes, off)
                         | (UNSAFE.getByte(bytes, ARRAY_BYTE_BASE_OFFSET + off + 2) << 16)
         );
     }
@@ -1554,7 +1550,7 @@ public class IOUtils {
 
     public static int digit2(byte[] bytes, int off) {
         return digit2(
-                getShortLittleEndian(bytes, off)
+                getShortE(bytes, off)
         );
     }
 
@@ -1616,36 +1612,42 @@ public class IOUtils {
         return ch >= '0' && ch <= '9';
     }
 
-    public static short getShortLittleEndian(byte[] bytes, int offset) {
-        short v = UNSAFE.getShort(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
-        if (BIG_ENDIAN) {
-            v = Short.reverseBytes(v);
-        }
-        return v;
+    public static short getShortE(byte[] bytes, int offset) {
+        return convEndian(false,
+                UNSAFE.getShort(bytes, ARRAY_BYTE_BASE_OFFSET + offset));
     }
 
-    public static int getIntLittleEndian(byte[] bytes, int offset) {
-        int v = UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
-        if (BIG_ENDIAN) {
-            v = Integer.reverseBytes(v);
-        }
-        return v;
+    public static int getIntBE(byte[] bytes, int offset) {
+        return convEndian(true,
+                UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset));
     }
 
-    public static long getLongBigEndian(byte[] bytes, int offset) {
-        long v = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
-        if (!BIG_ENDIAN) {
-            v = Long.reverseBytes(v);
-        }
-        return v;
+    public static int getIntLE(byte[] bytes, int offset) {
+        return convEndian(false,
+                UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + offset));
     }
 
-    public static long getLongLittleEndian(byte[] bytes, int offset) {
-        long v = UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset);
-        if (BIG_ENDIAN) {
-            v = Long.reverseBytes(v);
-        }
-        return v;
+    public static int getIntUnaligned(char[] bytes, int offset) {
+        return UNSAFE.getInt(bytes, ARRAY_BYTE_BASE_OFFSET + ((long) offset << 1));
+    }
+
+    public static long getLongBE(byte[] bytes, int offset) {
+        return convEndian(true,
+                UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset));
+    }
+
+    public static long getLongUnaligned(char[] bytes, int offset) {
+        return UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + ((long) offset << 1));
+    }
+
+    public static long getLongLE(byte[] bytes, int offset) {
+        return convEndian(false,
+                UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + offset));
+    }
+
+    public static long getLongLE(char[] bytes, int offset) {
+        return convEndian(false,
+                UNSAFE.getLong(bytes, ARRAY_BYTE_BASE_OFFSET + ((long) offset << 1)));
     }
 
     public static short hex2(int i) {
@@ -1655,30 +1657,42 @@ public class IOUtils {
                 + 0x30303030 + i);
     }
 
-    public static int hex4(int i) {
+    public static int utf16Hex2(int i) {
+        // 0x000F000F
+        i = ((i & 0xF0) >> 4) | ((i & 0xF) << 16);
+        int m = (i + 0x00060006) & 0x00100010;
+        return ((m << 1) + (m >> 1) - (m >> 4))
+                + 0x00300030 + i;
+    }
+
+    public static int hex4U(int i) {
         i = reverseBytesExpand(i);
         /*
-            0  = 0b0000_0000 => m = ((x + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0  + 0x30 + (x & 0xF) => 0
-            1  = 0b0000_0001 => m = ((x + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0  + 0x30 + (x & 0xF) => 1
-            2  = 0b0000_0010 => m = ((x + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0  + 0x30 + (x & 0xF) => 2
-            3  = 0b0000_0011 => m = ((x + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0  + 0x30 + (x & 0xF) => 3
-            4  = 0b0000_0100 => m = ((x + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0  + 0x30 + (x & 0xF) => 4
-            5  = 0b0000_0101 => m = ((x + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0  + 0x30 + (x & 0xF) => 5
-            6  = 0b0000_0110 => m = ((x + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0  + 0x30 + (x & 0xF) => 6
-            7  = 0b0000_0111 => m = ((x + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0  + 0x30 + (x & 0xF) => 7
-            8  = 0b0000_1000 => m = ((x + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0  + 0x30 + (x & 0xF) => 8
-            9  = 0b0000_1001 => m = ((x + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 0  + 0x30 + (x & 0xF) => 9
-            10 = 0b0000_1010 => m = ((x + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (x & 0xF) => a
-            11 = 0b0000_1011 => m = ((x + 6) & 0x10); (m << 1) + (m >> 1) - (m >> 4) => 39 + 0x30 + (x & 0xF) => b
+            0  = 0b0000_0000 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 0 + 0x30 + (x & 0xF) => 0
+            1  = 0b0000_0001 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 0 + 0x30 + (x & 0xF) => 1
+            2  = 0b0000_0010 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 0 + 0x30 + (x & 0xF) => 2
+            3  = 0b0000_0011 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 0 + 0x30 + (x & 0xF) => 3
+            4  = 0b0000_0100 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 0 + 0x30 + (x & 0xF) => 4
+            5  = 0b0000_0101 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 0 + 0x30 + (x & 0xF) => 5
+            6  = 0b0000_0110 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 0 + 0x30 + (x & 0xF) => 6
+            7  = 0b0000_0111 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 0 + 0x30 + (x & 0xF) => 7
+            8  = 0b0000_1000 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 0 + 0x30 + (x & 0xF) => 8
+            9  = 0b0000_1001 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 0 + 0x30 + (x & 0xF) => 9
+            10 = 0b0000_1010 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 7 + 0x30 + (x & 0xF) => A
+            11 = 0b0000_1011 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 7 + 0x30 + (x & 0xF) => B
+            12 = 0b0000_1100 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 7 + 0x30 + (x & 0xF) => C
+            13 = 0b0000_1101 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 7 + 0x30 + (x & 0xF) => D
+            14 = 0b0000_1110 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 7 + 0x30 + (x & 0xF) => E
+            15 = 0b0000_1111 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 7 + 0x30 + (x & 0xF) => F
          */
         int m = (i + 0x06060606) & 0x10101010;
-        return ((m << 1) + (m >> 1) - (m >> 4))
+        return ((m >> 1) - (m >> 4))
                 + 0x30303030
                 + i;
     }
 
-    public static int hex4U(int i) {
-        i = reverseBytesExpand(i);
+    public static long utf16Hex4U(long i) {
+        i = utf16ReverseBytesExpand(i);
         /*
             0  = 0b0000_0000 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 0 + 0x30 + (x & 0xF) => 0
             1  = 0b0000_0001 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 0 + 0x30 + (x & 0xF) => 1
@@ -1697,9 +1711,9 @@ public class IOUtils {
             14 = 0b0000_1110 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 7 + 0x30 + (x & 0xF) => E
             15 = 0b0000_1111 => m = ((x + 6) & 0x10); (m >> 1) - (m >> 4) => 7 + 0x30 + (x & 0xF) => F
          */
-        int m = (i + 0x06060606) & 0x10101010;
+        long m = (i + 0x00060006_00060006L) & 0x00100010_00100010L;
         return ((m >> 1) - (m >> 4))
-                + 0x30303030
+                + 0x00300030_00300030L
                 + i;
     }
 
@@ -1708,4 +1722,21 @@ public class IOUtils {
         i = ((i & 0xF000) >> 12) | (i & 0xF00) | ((i & 0xF0) << 12) | ((i & 0xF) << 24);
         return i;
     }
+
+    private static long utf16ReverseBytesExpand(long i) {
+        // i = Long.reverseBytes(Long.expand(i, 0x00F000F0_00F000F0));
+        return ((i & 0xF000L) >> 12) | ((i & 0xF00L) << 8) | ((i & 0xF0L) << 28) | ((i & 0xFL) << 48);
+    }
+
+    static int convEndian(boolean big, int n) {
+        return big == BIG_ENDIAN ? n : Integer.reverseBytes(n);
+    }
+
+    static long convEndian(boolean big, long n) {
+        return big == BIG_ENDIAN ? n : Long.reverseBytes(n);
+    }
+
+    static short convEndian(boolean big, short n) {
+        return big == BIG_ENDIAN ? n : Short.reverseBytes(n);
+    }
 }


Test patch:
diff --git a/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/jjb/ClientsWriteCNBytesTest.java b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/jjb/ClientsWriteCNBytesTest.java
new file mode 100644
index 000000000..907869130
--- /dev/null
+++ b/benchmark/src/test/java/com/alibaba/fastjson2/benchmark/jjb/ClientsWriteCNBytesTest.java
@@ -0,0 +1,109 @@
+package com.alibaba.fastjson2.benchmark.jjb;
+
+import static com.alibaba.fastjson2.benchmark.JMH.BH;
+
+public class ClientsWriteCNBytesTest {
+    static final ClientsWriteCNBytes benchmark = new ClientsWriteCNBytes();
+
+    public static void jsonb() {
+        for (int j = 0; j < 5; j++) {
+            long start = System.currentTimeMillis();
+            for (int i = 0; i < 1000 * 1000; ++i) {
+                benchmark.jsonb(BH);
+            }
+            long millis = System.currentTimeMillis() - start;
+            System.out.println("ClientsWriteUTF8Bytes-jsonb millis : " + millis);
+            // zulu17.40.19 : 609
+            // zulu17.40.19_vec :
+        }
+    }
+
+    public static void jsonb_beanToArray() {
+        for (int j = 0; j < 5; j++) {
+            long start = System.currentTimeMillis();
+            for (int i = 0; i < 1000 * 1000; ++i) {
+                benchmark.jsonb_beanToArray(BH);
+            }
+            long millis = System.currentTimeMillis() - start;
+            System.out.println("ClientsWriteUTF8Bytes-jsonb_beanToArray millis : " + millis);
+            // zulu17.40.19 : 311 303
+            // zulu17.40.19_vec :
+        }
+    }
+
+    public static void fastjson2() {
+        for (int j = 0; j < 5; j++) {
+            long start = System.currentTimeMillis();
+            for (int i = 0; i < 1000 * 1000; ++i) {
+                benchmark.fastjson2(BH);
+            }
+            long millis = System.currentTimeMillis() - start;
+            System.out.println("ClientsWriteUTF8Bytes-fastjson2 millis : " + millis);
+            // zulu8.70.0.23 :
+            // zulu17.40.19 : 1027
+            // zulu17.40.19_vec :
+            // zulu17.40.19_reflect :
+        }
+    }
+
+    public static void wast() {
+        for (int j = 0; j < 5; j++) {
+            long start = System.currentTimeMillis();
+            for (int i = 0; i < 1000 * 1000; ++i) {
+                benchmark.wast(BH);
+            }
+            long millis = System.currentTimeMillis() - start;
+            System.out.println("ClientsWriteUTF8Bytes-wast millis : " + millis);
+            // zulu8.70.0.23 :
+            // zulu17.40.19 : 1364
+            // zulu17.40.19_vec :
+            // zulu17.40.19_reflect :
+        }
+    }
+
+    public static void fastjson2_str() {
+        for (int j = 0; j < 5; j++) {
+            long start = System.currentTimeMillis();
+            for (int i = 0; i < 1000 * 1000; ++i) {
+                benchmark.fastjson2_str(BH);
+            }
+            long millis = System.currentTimeMillis() - start;
+            System.out.println("ClientsWriteUTF8Bytes-fastjson2 millis : " + millis);
+            // zulu17.40.19 :
+            // zulu17.40.19_vec : 1139 1313 1307 1206
+        }
+    }
+
+    public static void dsljson() throws Exception {
+        for (int j = 0; j < 5; j++) {
+            long start = System.currentTimeMillis();
+            for (int i = 0; i < 1000 * 1000; ++i) {
+                benchmark.dsljson(BH);
+            }
+            long millis = System.currentTimeMillis() - start;
+            System.out.println("ClientsWriteUTF8Bytes-dsljson millis : " + millis);
+            // zulu17.40.19 : 2169 1487
+        }
+    }
+
+    public static void jackson() throws Exception {
+        for (int j = 0; j < 10; j++) {
+            long start = System.currentTimeMillis();
+            for (int i = 0; i < 1000 * 1000; ++i) {
+                benchmark.jackson(BH);
+            }
+            long millis = System.currentTimeMillis() - start;
+            System.out.println("jackson millis : " + millis);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        fastjson2();
+//        wast();
+//        jsonb();
+//        jsonb_beanToArray();
+//        fastjson2_str();
+//        dsljson();
+//        jackson();
+    }
+}
diff --git a/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16Test.java b/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16Test.java
index b157d577a..4445bd4c5 100644
--- a/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16Test.java
+++ b/core/src/test/java/com/alibaba/fastjson2/JSONWriterUTF16Test.java
@@ -1,6 +1,7 @@
 package com.alibaba.fastjson2;
 
 import com.alibaba.fastjson2.annotation.JSONField;
+import com.alibaba.fastjson2.util.IOUtils;
 import org.junit.jupiter.api.Test;
 
 import java.math.BigDecimal;
@@ -14,9 +15,10 @@ import java.util.UUID;
 
 import static com.alibaba.fastjson2.JSONWriter.Feature.*;
 import static com.alibaba.fastjson2.JSONWriter.Feature.BrowserSecure;
+import static com.alibaba.fastjson2.JSONWriterUTF16.BYTE_VEC_64_DOUBLE_QUOTE;
+import static com.alibaba.fastjson2.JSONWriterUTF16.BYTE_VEC_64_SINGLE_QUOTE;
 import static com.alibaba.fastjson2.util.JDKUtils.*;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.*;
 
 public class JSONWriterUTF16Test {
     @Test
@@ -1083,4 +1085,157 @@ public class JSONWriterUTF16Test {
             }
         }
     }
+
+    @Test
+    public void testEscaped() {
+        char[] chars = new char[] {'"', '"', '"', '"'};
+        byte[] bytes = toBytes(chars);
+
+        JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+        jsonWriter.writeStringUTF16(bytes);
+        String str = jsonWriter.toString();
+        System.out.println(str);
+        assertEquals("\"\\\"\\\"\\\"\\\"\"", str);
+    }
+
+    @Test
+    public void testEscaped_1() {
+        String str = "😀😉";
+        char[] chars = str.toCharArray();
+        byte[] bytes = toBytes(chars);
+
+        JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+        jsonWriter.writeStringUTF16(bytes);
+        assertEquals("\"" + str + "\"", jsonWriter.toString());
+    }
+
+    @Test
+    public void testEscaped_2() {
+        String str = "abcd";
+        char[] chars = str.toCharArray();
+        byte[] bytes = toBytes(chars);
+
+        long v = IOUtils.getLongLE(bytes, 0);
+        assertFalse(
+                JSONWriterUTF16.containsEscapedUTF16(
+                        v,
+                        BYTE_VEC_64_DOUBLE_QUOTE));
+
+        JSONWriterUTF16 jsonWriter = (JSONWriterUTF16) JSONWriter.ofUTF16();
+        jsonWriter.writeStringUTF16(bytes);
+        assertEquals("\"" + str + "\"", jsonWriter.toString());
+    }
+
+    @Test
+    public void test_containsEscapedUTF16() {
+        char[] chars = new char[4];
+        char[] specials_double = new char[]{'\\', '"', '\r', '\n'};
+        char[] specials_single = new char[]{'\\', '\'', '\r', '\n'};
+        {
+            Arrays.fill(chars, 'A');
+            {
+                long v = IOUtils.getLongLE(
+                        toBytes(chars),
+                        0);
+                assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+            }
+
+            {
+                chars[0] = '"';
+                long v = IOUtils.getLongLE(
+                        toBytes(chars),
+                        0);
+                assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
+                assertTrue(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+            }
+            {
+                chars[0] = '\'';
+                long v = IOUtils.getLongLE(
+                        toBytes(chars),
+                        0);
+                assertTrue(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
+                assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+            }
+        }
+        {
+            Arrays.fill(chars, '中');
+            {
+                long v = IOUtils.getLongLE(
+                        toBytes(chars),
+                        0);
+                assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+            }
+        }
+        {
+            Arrays.fill(chars, '®');
+            {
+                long v = IOUtils.getLongLE(
+                        toBytes(chars),
+                        0);
+                assertTrue(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+            }
+        }
+
+        for (int i = 0; i < 4; i++) {
+            Arrays.fill(chars, 'A');
+            for (char c : specials_double) {
+                chars[i] = c;
+                long v = IOUtils.getLongLE(
+                        toBytes(chars),
+                        0);
+                assertTrue(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+            }
+            for (char c : specials_single) {
+                chars[i] = c;
+                long v = IOUtils.getLongLE(
+                        toBytes(chars),
+                        0);
+                assertTrue(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
+            }
+        }
+        {
+            chars = new char[]{'a', 'b', 'c', 'd'};
+            long v = IOUtils.getLongLE(
+                    toBytes(chars),
+                    0);
+            assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
+            assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+        }
+        {
+            chars = new char[]{'A', 'B', 'C', 'D'};
+            long v = IOUtils.getLongLE(
+                    toBytes(chars),
+                    0);
+            assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_SINGLE_QUOTE));
+            assertFalse(JSONWriterUTF16.containsEscapedUTF16(v, BYTE_VEC_64_DOUBLE_QUOTE));
+        }
+    }
+
+    static byte[] toBytes(char[] chars) {
+        if (chars.length != 4) {
+            throw new UnsupportedOperationException();
+        }
+        byte[] bytes = new byte[chars.length << 1];
+        long x = IOUtils.getLongLE(chars, 0);
+        IOUtils.putLongLE(bytes, 0, x);
+        return bytes;
+    }
+
+    @Test
+    public void write2() {
+        char[] chars = new char[4];
+        JSONWriterUTF16.writeEscapedChar(chars, 0, '\r');
+        JSONWriterUTF16.writeEscapedChar(chars, 2, '\n');
+        assertEquals("\\r\\n", new String(chars));
+    }
+
+    @Test
+    public void writeU4() {
+        char[] chars = new char[6];
+        JSONWriterUTF16.writeU4Hex2(chars, 0, 1);
+        assertEquals("\\u0001", new String(chars));
+
+        IOUtils.putLongUnaligned(chars, 2, IOUtils.utf16Hex4U(1));
+        assertEquals("\\u0001", new String(chars));
+    }
 }
diff --git a/core/src/test/java/com/alibaba/fastjson2/util/IOUtilsTest.java b/core/src/test/java/com/alibaba/fastjson2/util/IOUtilsTest.java
index 05f33de80..09a234b59 100644
--- a/core/src/test/java/com/alibaba/fastjson2/util/IOUtilsTest.java
+++ b/core/src/test/java/com/alibaba/fastjson2/util/IOUtilsTest.java
@@ -4,11 +4,11 @@ import com.alibaba.fastjson2.JSONException;
 import org.junit.jupiter.api.Test;
 
 import java.nio.charset.StandardCharsets;
+import java.util.Random;
 
 import static com.alibaba.fastjson2.util.JDKUtils.ARRAY_BYTE_BASE_OFFSET;
 import static com.alibaba.fastjson2.util.JDKUtils.UNSAFE;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.*;
 
 public class IOUtilsTest {
     @Test
@@ -373,4 +373,21 @@ public class IOUtilsTest {
                 IOUtils.indexOfChar(
                         bytes, 'a', 1));
     }
+
+    @Test
+    public void convEndian() throws Throwable {
+        Random r = new Random();
+        long i64 = r.nextLong();
+        int i32 = r.nextInt();
+        short i16 = (short) r.nextInt();
+
+        assertEquals(i64, IOUtils.convEndian(false, i64));
+        assertEquals(Long.reverseBytes(i64), IOUtils.convEndian(true, i64));
+
+        assertEquals(i32, IOUtils.convEndian(false, i32));
+        assertEquals(Integer.reverseBytes(i32), IOUtils.convEndian(true, i32));
+
+        assertEquals(i16, IOUtils.convEndian(false, i16));
+        assertEquals(Short.reverseBytes(i16), IOUtils.convEndian(true, i16));
+    }
 }