Kotlin字节序问题排查:跨平台字节数组反序列化异常
字节序不匹配导致长整型反序列化错误排查
问题背景
- 运行在Ubuntu上的C++应用以小端序序列化长整型数据,例如数值
1000L被序列化为字节数组[-24, 3, 0, 0, 0, 0, 0, 0]。 - MacOS M1芯片编译的Android应用(Kotlin)中,系统原生字节序为小端,但使用默认
ByteBuffer转换时,1000L被序列化为[0,0,0,0,0,0,3,-24](大端序);反序列化C++传来的字节数组时,得到异常值-1728537831980138496而非预期的1000L。
核心原因
ByteBuffer的默认字节序是大端序(BIG_ENDIAN),与系统原生字节序无关。即使你的Android设备是小端架构,直接使用未指定字节序的ByteBuffer,会默认按大端规则处理字节数组,导致与C++的小端数据格式不匹配,最终转换出错误数值。
解决方案
修改Kotlin的字节数组与长整型转换函数,明确指定ByteBuffer使用小端序,与C++端的序列化规则保持一致:
fun isLittleEndian(): Boolean { return ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN } /** * 将长整型转换为小端序字节数组 */ fun Long.toBytes(): ByteArray { return ByteBuffer.allocate(Long.SIZE_BYTES) .order(ByteOrder.LITTLE_ENDIAN) // 指定小端序 .putLong(this) .array() } /** * 将小端序字节数组转换为长整型 */ fun ByteArray.toLong(): Long { return ByteBuffer.wrap(this) .order(ByteOrder.LITTLE_ENDIAN) // 指定小端序 .long } fun test() { val longNumber = 1000L val isLittleEndian = isLittleEndian() // 返回true val bytes = longNumber.toBytes() // 输出:[-24, 3, 0, 0, 0, 0, 0, 0],与C++一致 val restoredNumber = bytes.toLong() // 输出:1000L,符合预期 }
额外说明
如果需要跨平台兼容性,也可以统一使用网络字节序(大端序),此时C++端需要将数据转换为大端后再序列化,Kotlin端保持默认ByteBuffer即可,但需要确保两端规则完全统一。
内容的提问来源于stack exchange,提问作者Nguyen Minh Binh
相关产品推荐
相关产品推荐

