diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
index 1aafc0620..8306bba9f 100644
--- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
+++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
@@ -1,8 +1,8 @@
 package net.mamoe.mirai.qqandroid.network
 
 import kotlinx.coroutines.*
-import kotlinx.io.core.ByteReadPacket
-import kotlinx.io.core.use
+import kotlinx.io.core.*
+import kotlinx.io.pool.ObjectPool
 import net.mamoe.mirai.data.Packet
 import net.mamoe.mirai.event.broadcast
 import net.mamoe.mirai.network.BotNetworkHandler
@@ -14,11 +14,8 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
 import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
 import net.mamoe.mirai.qqandroid.network.protocol.packet.login.RegPushReason
 import net.mamoe.mirai.qqandroid.network.protocol.packet.login.SvcReqRegisterPacket
-import net.mamoe.mirai.utils.LockFreeLinkedList
-import net.mamoe.mirai.utils.MiraiInternalAPI
-import net.mamoe.mirai.utils.getValue
+import net.mamoe.mirai.utils.*
 import net.mamoe.mirai.utils.io.*
-import net.mamoe.mirai.utils.unsafeWeakRef
 import kotlin.coroutines.CoroutineContext
 
 @UseExperimental(MiraiInternalAPI::class)
@@ -46,25 +43,137 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
         SvcReqRegisterPacket(bot.client, RegPushReason.setOnlineStatus).sendAndExpect<SvcReqRegisterPacket.Response>()
     }
 
-    internal fun launchPacketProcessor(rawInput: ByteReadPacket): Job = launch(CoroutineName("Incoming Packet handler")) {
-        rawInput.debugPrint("Received").use { input ->
-            if (input.remaining == 0L) {
-                bot.logger.error("Empty packet received. Consider if bad packet was sent.")
-                return@launch
+    /**
+     * 单线程处理包的接收, 分割和连接.
+     */
+    @Suppress("PrivatePropertyName")
+    private val PacketReceiveDispatcher = newCoroutineDispatcher(1)
+
+    /**
+     * 单线程处理包的解析 (协程挂起效率够)
+     */
+    @Suppress("PrivatePropertyName")
+    private val PacketProcessDispatcher = newCoroutineDispatcher(1)
+
+    /**
+     * 缓存的包
+     */
+    private var cachedPacket: ByteReadPacket? = null
+    /**
+     * 缓存的包还差多少长度
+     */
+    private var expectingRemainingLength: Long = 0
+
+    /**
+     * 在 [PacketProcessDispatcher] 调度器中解析包内容.
+     * [input] 将会被 [ObjectPool.recycle].
+     *
+     * @param input 一个完整的包的内容, 去掉开头的 int 包长度
+     */
+    fun parsePacketAsync(input: IoBuffer, pool: ObjectPool<IoBuffer> = IoBuffer.Pool): Job =
+        this.launch(PacketProcessDispatcher) {
+            try {
+                parsePacket(input)
+            } finally {
+                input.discard()
+                input.release(pool)
             }
-            KnownPacketFactories.parseIncomingPacket(bot, input) { packet: Packet, packetId: PacketId, sequenceId: Int ->
-                if (PacketReceivedEvent(packet).broadcast().cancelled) {
-                    return@parseIncomingPacket
-                }
-                packetListeners.forEach { listener ->
-                    if (listener.filter(packetId, sequenceId) && packetListeners.remove(listener)) {
-                        listener.complete(packet)
-                    }
+        }
+
+    /**
+     * 在 [PacketProcessDispatcher] 调度器中解析包内容.
+     * [input] 将会被 [Input.close], 因此 [input] 不能为 [IoBuffer]
+     *
+     * @param input 一个完整的包的内容, 去掉开头的 int 包长度
+     */
+    fun parsePacketAsync(input: Input): Job {
+        require(input !is IoBuffer) { "input cannot be IoBuffer" }
+        return this.launch(PacketProcessDispatcher) {
+            input.use { parsePacket(it) }
+        }
+    }
+
+    /**
+     * 解析包内容
+     * **注意**: 需要函数调用者 close 这个 [input]
+     *
+     * @param input 一个完整的包的内容, 去掉开头的 int 包长度
+     */
+    suspend fun parsePacket(input: Input) {
+        KnownPacketFactories.parseIncomingPacket(bot, input) { packet: Packet, packetId: PacketId, sequenceId: Int ->
+            if (PacketReceivedEvent(packet).broadcast().cancelled) {
+                return@parseIncomingPacket
+            }
+            packetListeners.forEach { listener ->
+                if (listener.filter(packetId, sequenceId) && packetListeners.remove(listener)) {
+                    listener.complete(packet)
                 }
             }
         }
     }
 
+    /**
+     * 处理从服务器接收过来的包. 这些包可能是粘在一起的, 也可能是不完整的. 将会自动处理
+     */
+    @UseExperimental(ExperimentalCoroutinesApi::class)
+    internal suspend fun processPacket(rawInput: ByteReadPacket): Unit = rawInput.debugPrint("Received").let { input: ByteReadPacket ->
+        if (input.remaining == 0L) {
+            return
+        }
+
+        if (cachedPacket == null) {
+            // 没有缓存
+            var length: Int = input.readInt() - 4
+            if (input.remaining == length.toLong()) {
+                // 捷径: 当包长度正好, 直接传递剩余数据.
+                parsePacketAsync(input)
+                return
+            }
+            // 循环所有完整的包
+            while (input.remaining > length) {
+                parsePacketAsync(input.readIoBuffer(length))
+
+                length = input.readInt() - 4
+            }
+
+            if (input.remaining != 0L) {
+                // 剩余的包长度不够, 缓存后接收下一个包
+                expectingRemainingLength = length - input.remaining
+                cachedPacket = input
+            } else {
+                cachedPacket = null // 表示包长度正好
+            }
+        } else {
+            // 有缓存
+
+            if (input.remaining >= expectingRemainingLength) {
+                // 剩余长度够, 连接上去, 处理这个包.
+                parsePacketAsync(buildPacket {
+                    writePacket(cachedPacket!!)
+                    writePacket(input, expectingRemainingLength)
+                })
+                cachedPacket = null // 缺少的长度已经给上了.
+
+                if (input.remaining != 0L) {
+                    processPacket(input) // 继续处理剩下内容
+                }
+            } else {
+                // 剩余不够, 连接上去
+                expectingRemainingLength -= input.remaining
+                cachedPacket = buildPacket {
+                    writePacket(cachedPacket!!)
+                    writePacket(input)
+                }
+            }
+        }
+        if (input.remaining == 0L) {
+            bot.logger.error("Empty packet received. Consider if bad packet was sent.")
+            return
+        }
+    }
+
+
+    @UseExperimental(ExperimentalCoroutinesApi::class)
     private suspend fun processReceive() {
         while (channel.isOpen) {
             val rawInput = try {
@@ -81,7 +190,9 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
                 bot.logger.error("Caught unexpected exceptions", e)
                 continue
             }
-            launchPacketProcessor(rawInput)
+            launch(context = PacketReceiveDispatcher + CoroutineName("Incoming Packet handler"), start = CoroutineStart.ATOMIC) {
+                processPacket(rawInput)
+            }
         }
     }
 
diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
index 6a091e427..f367c2e0d 100644
--- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
+++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
@@ -62,16 +62,13 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
     // 00 00 08 E0 00 00 00 0A 01 00 00 00 00 0E 31 39 39 34 37 30 31 30 32 31 B4 16 A6 D7 A3 E4 9E 53 99 CD 77 14 70 1F 51 3E 8B 79 F6 93 2B E0 92 E4 32 E2 87 6C 3A 9C 1B 29 87 CB 3C 60 45 9C 41 71 63 6A F6 99 FC 05 01 68 86 B3 6F 37 97 52 C5 D3 0E 66 B3 F6 40 CC EB 18 A3 AE 15 3E 31 B1 E9 7C 6F EC E4 4D 31 F1 1E 2C 0C 1C 45 66 CD F7 1B 90 11 9A D8 CE DD 6D 6C 63 9F EB CD 69 33 AF 6C 8E BA 8C CB C3 FF 27 A2 A6 C3 28 06 4A B5 79 79 12 AB 52 04 62 CA 7D 11 59 85 5C 0B D6 8D 2A E7 9C 04 97 62 7D 05 11 3E 2C 11 60 E3 E3 B3 DA 7A 7C 13 AF 22 01 53 80 69 D0 F9 C8 86 EC 25 8C F3 67 5C 82 45 08 FB 34 43 50 01 0E EA 43 77 D8 CF EC 55 E6 4E 66 5B 26 21 C9 E8 78 92 AE 5C 61 F0 5E 0B E7 34 1F 53 D6 EA 28 9C 02 1A E9 F0 55 61 4B 06 F8 56 3B AC 93 B2 2C CD 66 0D D1 18 CB BD 29 50 DE 0F 82 6D 28 63 AB 21 E1 6C BA B1 9F 69 A4 E3 C9 20 F8 11 82 39 04 2B 54 44 50 FA 2E 86 68 6D DC 5D 9E 18 F4 DD 19 09 BC CF E8 41 68 A3 8D 86 42 80 51 C4 C1 ED 54 DB 50 F5 1D A7 28 2A 0D E8 14 1A 4E F7 96 29 00 6C 9D 4A 2E 3E 7B 4C AC 20 78 F1 3C 70 6B 61 96 D7 EC 77 AD CB AD AF BB 47 C3 1F A0 6C 6C 9C 9F F3 6C EB 6C A4 D0 7F 2B E1 AA 68 26 99 B9 C8 A1 F5 C4 7E E7 E7 81 EE 66 00 96 33 49 C0 EE A2 F9 F6 52 C5 A6 5D EE 9D C5 E5 CE DA 31 FC FF 4B 02 97 68 3D 6A 99 4A CF 69 D9 F4 53 68 31 E7 32 2F 85 E7 7F 16 82 AE FA 73 D5 42 09 9C CB 53 26 79 41 63 80 B0 E2 6A 8B B9 C6 71 08 B4 2B E0 48 D3 C4 0F B0 00 D0 FA 8C 29 DE E9 71 6A D7 89 76 E7 5D 33 14 10 6F E2 44 6A A0 DC C1 CB F3 9A C3 13 CB D1 82 2C DF 34 68 79 E3 09 BD CC 2B 25 79 A8 E7 BE 29 6C 97 C3 D7 F4 0E CC 2B 74 71 02 BA 2B 5B 57 1B C2 C8 C2 BF 54 23 72 EA E4 38 54 20 7D 88 E4 39 7C C5 8A 1B C0 EC D2 1E 7D 1B 6B 7A BC EC 73 1E 53 4A 6F 4F EA F0 56 12 80 BD 0B 37 67 BD FD A8 29 23 2D 8E 66 7E 31 A9 F6 CE 7E BC 4F 38 D0 33 D4 C7 4A E9 43 9D 28 2E 8F 7C D5 81 F4 8C F9 6F 21 AC A1 08 FD F4 01 FB E8 CE 61 91 BE 68 5B E4 3A 5F F8 FB DA 5D 9B 2A AF E2 0C D3 A4 1F 42 90 96 E1 28 44 85 8D E1 CF 19 A9 47 04 8D 28 D9 B3 35 79 48 70 D9 ED 45 B6 24 B5 56 FA 1E DE 02 F3 EB 69 08 7D 24 9C 60 35 97 8D 13 4A 5A 57 BA B3 14 C1 EE 70 22 CA B2 65 F7 BB 3F A2 D9 14 AA 4C 52 E6 E4 10 D3 FD C6 2B DD BF C0 CF E5 35 57 9E 9F D0 77 C8 E6 EF 2B 8E 01 88 96 F8 68 95 A7 0D 58 81 30 60 88 44 CC 31 5B C1 D4 92 6E ED 17 CA 0A 01 69 90 4E 6A C0 D7 09 6C E5 33 64 CA 6E 5C 07 C3 AD 46 36 F9 DF DE B7 71 B2 87 CB 3D 76 C0 44 B8 6B 15 27 B2 03 99 C7 51 8A 00 35 C9 1C 76 55 32 AE 49 5A 34 6A 4E FD 20 7A 24 BF 34 E8 B4 18 BC 92 64 A1 F3 0A 2E 7B 00 EA B6 52 E7 AC 34 FD AE FF 1E 5D 6D D6 1F 6D 06 31 09 9D A9 9C 86 DB 5E 05 07 BA 4A 49 2B D2 7F EE 88 64 B2 6F 15 70 39 1B E9 57 6A 4E 29 4A A4 57 EA 80 3D 86 4C E9 F7 F5 2B C4 9F 35 62 76 09 0E 1C A4 99 50 99 82 2F 84 90 0E 9E 9F 75 C3 15 B0 61 34 D1 67 2D 30 16 FE D3 BF 59 6A B1 74 02 C4 EF 92 85 E0 16 4B 0C C5 9D 65 BB 5D 52 8F 52 5B 7C 7B 74 D9 EC 41 A9 5B FA 2D 95 D4 AE 5D F1 68 88 F6 82 ED 09 05 21 2E 5D 93 64 A0 96 15 64 A6 50 3C 03 2B FC 3E 80 89 90 62 CC D9 23 8E D7 BD 05 02 30 86 32 31 6A 5F F8 C4 BD 61 D0 CE B9 54 4E 93 E9 AE B9 4F 2B 98 DC 23 31 CC A8 06 89 A8 08 60 99 DC D4 81 98 13 C9 27 36 32 24 C1 B0 6B F0 3D EB CC 3B 32 5F 20 72 23 B3 DF 0B 48 3C 35 FD F1 FB DC 3E 2A BE B9 0F 42 56 F1 39 94 86 85 C6 1E A0 4C EC B8 69 45 5F 3D AB 3C 3B A2 70 61 91 9D 2C DD 6D C5 E9 EF 47 36 A6 A3 E0 96 C2 B8 EF 92 E9 E0 26 88 C6 B5 51 BA DE FD C5 BA 4C 6A 9A FE 6F DE B8 10 05 7F 9C 5D 40 11 39 75 CD 36 4F 6B A8 A1 94 57 5F 8F F2 D0 E2 36 A0 A4 24 05 FD 9E F5 51 93 C9 6E 5A 10 8D C3 33 2D E5 09 7A E0 DB 44 63 9C EA A5 ED BF 0B 98 32 F1 BA 04 96 F6 14 49 F1 F8 58 EA 6E 5E 5E 49 CA 2D E2 93 E6 AD 20 B2 CD 98 A7 3E BA 3E A8
 
 
+    /**
+     * full packet without length
+     */
     // do not inline. Exceptions thrown will not be reported correctly
-    suspend fun parseIncomingPacket(bot: QQAndroidBot, rawInput: ByteReadPacket, consumer: PacketConsumer) =
+    suspend fun parseIncomingPacket(bot: QQAndroidBot, rawInput: Input, consumer: PacketConsumer) =
         rawInput.debugIfFail("Incoming packet") {
             require(remaining < Int.MAX_VALUE) { "rawInput is too long" }
-            val expectedLength = readUInt().toInt() - 4
-            if (expectedLength > 16e7) {
-                bot.logger.warning("Detect incomplete packet, ignoring.")
-                return@debugIfFail
-            }
-            check(remaining.toInt() == expectedLength) { "Invalid packet length. Expected $expectedLength, got ${this.remaining} Probably packets merged? " }
             // login
             val flag1 = readInt()
 
@@ -88,12 +85,12 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
             //debugPrint("remaining")
 
             when (flag1) {
-                0x0A -> parseLoginSsoPacket(bot, decryptBy(DECRYPTER_16_ZERO), consumer)
+                0x0A -> parseLoginSsoPacket(bot, if (flag2 == 2) decryptBy(DECRYPTER_16_ZERO) else decryptBy(bot.client.wLoginSigInfo.d2Key), consumer)
                 0x0B -> parseUniPacket(bot, decryptBy(DECRYPTER_16_ZERO), consumer)
             }
         }
 
-    private suspend fun parseUniPacket(bot: QQAndroidBot, rawInput: ByteReadPacket, consumer: PacketConsumer) =
+    private fun parseUniPacket(bot: QQAndroidBot, rawInput: ByteReadPacket, consumer: PacketConsumer) =
         rawInput.debugIfFail("Login sso packet") {
             readIoBuffer(readInt() - 4).withUse {
                 //00 01 4E 64 FF FF D8 E8 00 00 00 14 6E 65 65 64 20 41 32 20 61 6E 64 20 49 4D 45 49 00 00 00 04 00 00 00 08 60 7F B6 23 00 00 00 00 00 00 00 04
diff --git a/mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt b/mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt
index 1e27f8ff2..78becc0cf 100644
--- a/mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt
+++ b/mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/clientToServer.kt
@@ -68,8 +68,12 @@ private val shareKeyCalculatedByConstPubKey = ECDH.calculateShareKey(
 )
 
 fun main() {
+
+
     val data = """
-20da22db750806141ef448110800450001b45126400080060000c0a8030a71600dd0fe501f908b8c585508ceeec6501801fc448900000000018c0000000a0100000044e0e22a59327abb9ce80cf63be86694210344fab2f2b065d7785a32cacfa4075cd509f49cb37a075ad0685cbd472344bfdef1ede611c0ad81129be9e2d7e476d2000000000e31393934373031303231f00754574170e9a5d13ca9426984103d1813e22d9c2147f8da5a0af64f64e4ebffde9ce8bfda6c1f798364a1de449adc701595fdce57fa4643e5e14eb4444ad0aea85261a6d5ee90c42a29b5af461a971a7fe85ecf1ed0d582d1cce60d1c34f6a3dc74a75d2f525d590da954098a1a7a4973773195dd209e662cb5c1e0db69843aa75425993bdc8876f21fd9c875d25fa47b689ebc302f3087de8e4a9862cff283703237602e50fa6bb281e974315b70f04f436d8ae9c5d67e22af3495e64aada419940e63c8d0ddbb066fa3d2b8cb27209a687d782d4ec32e6505593625bf0de257d59332f779ed6edb849502591e2c37b983974dbc3ec4740dfd0a9244baf958219067ca7d435ec8bde8e57b36f04d31622a86cb9c8d59d81074c9af38d57f42bb331a0a15f9ac5e216ae54abe8f8a
+20da22db750806141ef448110800450000d4512f400080060000c0a8030a71600dd0fe501f908b8c5c9908cf2416501801ff43a90000000000ac0000000b0100014f0d000000000e3139393437303130323193c94c8ce2871f6d5f6664df9e9231dedce5c7cb914cf5d616cf64af478aea9f210098e7f5efae9a952742b8fff704681885e5cc14a44e40d88910258f4a4a5cfcadd642cc159fdc475478475b18ba225cfad1c8bc2c5c828a9cc3ebaed1aa040d04b94f577fcfdb0861fd19754622733a242c5bcb37ca8597a2935d9910162111e44839b6787bb9be80058ad9c921c2
+
+
  """.trimIndent()
         .trim().split("\n").map {
             val bytes = it.trim().autoHexToBytes()
diff --git a/mirai-core-qqandroid/src/jvmTest/kotlin/test/dumpProtobufId.kts b/mirai-core-qqandroid/src/jvmTest/kotlin/test/dumpProtobufId.kts
index 6284e937d..4c9728774 100644
--- a/mirai-core-qqandroid/src/jvmTest/kotlin/test/dumpProtobufId.kts
+++ b/mirai-core-qqandroid/src/jvmTest/kotlin/test/dumpProtobufId.kts
@@ -3,7 +3,8 @@
 package test
 
 import net.mamoe.mirai.utils.cryptor.protoFieldNumber
+import net.mamoe.mirai.utils.cryptor.protoType
 
-intArrayOf(10, 18, 26, 34, 42, 50, 58, 66, 74).forEach {
-    println(protoFieldNumber(it.toUInt()))
+intArrayOf(8, 18, 26, 34, 80).forEach {
+    println(protoFieldNumber(it.toUInt()).toString() + " -> " + protoType(it.toUInt()))
 }
\ No newline at end of file
diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsAndroid.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsAndroid.kt
index c4d80af76..d2bb58323 100644
--- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsAndroid.kt
+++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsAndroid.kt
@@ -3,12 +3,15 @@ package net.mamoe.mirai.utils
 import io.ktor.client.HttpClient
 import io.ktor.client.engine.cio.CIO
 import io.ktor.util.KtorExperimentalAPI
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.asCoroutineDispatcher
 import java.io.ByteArrayOutputStream
 import java.io.DataInput
 import java.io.EOFException
 import java.io.InputStream
 import java.net.InetAddress
 import java.security.MessageDigest
+import java.util.concurrent.Executors
 import java.util.zip.CRC32
 import java.util.zip.Inflater
 
@@ -91,4 +94,8 @@ actual fun ByteArray.unzip(): ByteArray {
     }
     inflater.end()
     return output.toByteArray()
+}
+
+actual fun newCoroutineDispatcher(threadCount: Int): CoroutineDispatcher {
+    return Executors.newFixedThreadPool(threadCount).asCoroutineDispatcher()
 }
\ No newline at end of file
diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt
index fbdcd67a7..974ed9d44 100644
--- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt
+++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt
@@ -4,6 +4,7 @@ package net.mamoe.mirai.utils
 
 import io.ktor.client.HttpClient
 import io.ktor.util.date.GMTDate
+import kotlinx.coroutines.CoroutineDispatcher
 
 /**
  * 时间戳
@@ -46,3 +47,5 @@ expect fun localIpAddress(): String
  * Ktor HttpClient. 不同平台使用不同引擎.
  */
 expect val Http: HttpClient
+
+expect fun newCoroutineDispatcher(threadCount: Int): CoroutineDispatcher
\ No newline at end of file
diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/DebugUtil.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/DebugUtil.kt
index c7dc58de5..fc0bf4bd0 100644
--- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/DebugUtil.kt
+++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/DebugUtil.kt
@@ -2,7 +2,10 @@ package net.mamoe.mirai.utils.io
 
 import kotlinx.io.core.*
 import kotlinx.io.pool.useInstance
-import net.mamoe.mirai.utils.*
+import net.mamoe.mirai.utils.DefaultLogger
+import net.mamoe.mirai.utils.MiraiDebugAPI
+import net.mamoe.mirai.utils.MiraiLogger
+import net.mamoe.mirai.utils.withSwitch
 import kotlin.contracts.ExperimentalContracts
 import kotlin.contracts.InvocationKind
 import kotlin.contracts.contract
@@ -74,7 +77,7 @@ inline fun <R> Input.debugIfFail(name: String = "", onFail: (ByteArray) -> ByteR
     ByteArrayPool.useInstance {
         val count = this.readAvailable(it)
         try {
-            return block(it.toReadPacket(0, count))
+            return it.toReadPacket(0, count).use(block)
         } catch (e: Throwable) {
             onFail(it.take(count).toByteArray()).readAvailable(it)
             DebugLogger.debug("Error in ByteReadPacket $name=" + it.toUHexString(offset = 0, length = count))
diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
index bbb4120f9..262fdb04c 100644
--- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
+++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
@@ -4,15 +4,15 @@ package net.mamoe.mirai.utils
 
 import io.ktor.client.HttpClient
 import io.ktor.client.engine.cio.CIO
-import kotlinx.io.core.IoBuffer
-import kotlinx.io.core.Output
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.asCoroutineDispatcher
 import kotlinx.io.core.copyTo
-import kotlinx.io.core.readBytes
 import kotlinx.io.streams.asInput
 import kotlinx.io.streams.asOutput
 import java.io.*
 import java.net.InetAddress
 import java.security.MessageDigest
+import java.util.concurrent.Executors
 import java.util.zip.CRC32
 import java.util.zip.Inflater
 
@@ -68,4 +68,8 @@ actual fun ByteArray.unzip(): ByteArray {
     }
     inflater.end()
     return output.toByteArray()
+}
+
+actual fun newCoroutineDispatcher(threadCount: Int): CoroutineDispatcher {
+    return Executors.newFixedThreadPool(threadCount).asCoroutineDispatcher()
 }
\ No newline at end of file
diff --git a/mirai-debug/src/main/kotlin/test/ProtoTest.kt b/mirai-debug/src/main/kotlin/test/ProtoTest.kt
index 29b43598c..47f8b367e 100644
--- a/mirai-debug/src/main/kotlin/test/ProtoTest.kt
+++ b/mirai-debug/src/main/kotlin/test/ProtoTest.kt
@@ -2,15 +2,17 @@
 
 package test
 
-import kotlinx.serialization.*
+import kotlinx.serialization.ImplicitReflectionSerializer
+import kotlinx.serialization.SerialId
+import kotlinx.serialization.Serializable
 import kotlinx.serialization.protobuf.ProtoBuf
 import kotlinx.serialization.protobuf.ProtoNumberType
 import kotlinx.serialization.protobuf.ProtoType
+import kotlinx.serialization.serializer
 import net.mamoe.mirai.utils.MiraiInternalAPI
 import net.mamoe.mirai.utils.cryptor.readProtoMap
 import net.mamoe.mirai.utils.io.hexToBytes
 import net.mamoe.mirai.utils.io.read
-import net.mamoe.mirai.utils.io.toUHexString
 import kotlin.reflect.KClass
 
 @Serializable
@@ -25,15 +27,14 @@ data class ProtoTest(
 
 @UseExperimental(MiraiInternalAPI::class)
 suspend fun main() {
-    println("PNG".toUtf8Bytes().toUHexString())
     deserializeTest()
 }
 
 suspend fun deserializeTest() {
     val bytes =
         """
-            
-           """.trimIndent()
+            08 02 1A 55 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 1A 25 2F 34 35 35 38 66 39 30 38 2D 37 62 39 61 2D 34 65 32 66 2D 38 63 36 39 2D 34 61 35 32 61 66 62 33 36 35 61 37 20 01 30 04 38 05 40 09 48 01 58 00 60 01 6A 0A 38 2E 32 2E 30 2E 31 32 39 36 70 E0 8C B2 F0 05 78 01 50 03
+             """.trimIndent()
             .replace("\n", " ")
             .replace("UVarInt", "", ignoreCase = true)
             .replace("uint", "", ignoreCase = true)