You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java无原始对象信息时反序列化对象及序列化流解析求助

解决Java序列化对象解析的StreamCorruptedException问题

首先,你遇到的java.io.StreamCorruptedException: invalid stream header: 30303061错误,根源在于你可能把十六进制字符串直接当作字节数据来处理了——30303061对应的ASCII是000a,这显然不是Java序列化的合法开头(Java序列化的魔数是十六进制的AC ED 00 05)。下面是一步步的解决步骤:

1. 预处理十六进制字符串

你用xxd -p fileName得到的十六进制内容带有空格分隔,首先要把所有空格去掉,变成连续的十六进制字符串:

bd40efbfbdefbfbd00000000000a7371007e00000aefbfbdefbfbdefbfbd2b020c49efbfbdefbfbdefbfbdefbfbd2b020c49efbfbd3fefbfbdefbfbdefbfbd126eefbfbdefbfbd40efbfbdefbfbd000000000a7371007e00000aefbfbdefbfbdefbfbdefbfbdefbfbd126eefbfbdefbfbdefbfbd53efbfbdefbfbdefbfbd16efbfbd3fefbfbdefbfbdefbfbdefbfbd45efbfbd40efbfbdefbfbd00000000000a7371007e00000aefbfbdefbfbdefbfbd3b645a1cefbfbdefbfbdd0b4395810624e3fefbfbd020c49efbfbd5e3540efbfbdefbfbd000000000a7371007e00000aefbfbdefbfbdefbfbdefbfbd126eefbfbdefbfbdefbfbdefbfbd1aefbfbdefbfbd76c8b43fefbfbdefbfbd53efbfbdefbfbdefbfbd1740efbfbdefbfbd00000000000a7371007e0000efbfbdc49befbfbdefbfbd53efbfbdcfbf50624defbfbdefbfbdefbfbd3fefbfbdefbfbd45efbfbdefbfbdefbfbd40efbfbdefbfbd000000000a7371007e0000efbfbdc9ba5e353f7cefbfbdefbfbd1cefbfbd083126efbfbd3fefbfbd2d0e560418efbfbd40efbfbdefbfbd00000000000a7371007e0000efbfbdefbfbdefbfbd45efbfbdefbfbdefbfbdefbfbdefbfbdefbfbdefbfbdefbfbd126eefbfbd3fefbfbdefbfbd45efbfbdefbfbdefbfbd40efbfbdefbfbd000000000a7371007e0000efbfbdefbfbd26efbfbd78efbfbdefbfbdefbfbdefbfbd6eefbfbdefbfbd4fefbfbd3b3fefbfbd10624defbfbdefbfbd40efbfbdefbfbd00000000000a7371007e00000aefbfbdefbfbd4fefbfbd3b645aefbfbdefbfbd126eefbfbdefbfbd503fefbfbdefbfbdefbfbd22efbfbdefbfbd6040efbfbdefbfbd000000000a7371007e0000efbfbdefbfbd49efbfbd5e353f7defbfbdefbfbd10624defbfbdefbfbd3fefbfbd083126efbfbd78efbfbd40efbfbdefbfbd00000000000a7371007e00000aefbfbdefbfbd26efbfbd78efbfbdefbfbdefbfbdefbfbdefbfbdefbfbd126eefbfbdefbfbd3fefbfbdefbfbd16efbfbd2b020c40efbfbdef

2. 将十六进制字符串正确转换为二进制字节数组

不要直接把十六进制字符串转成字节数组(那样会把每个字符比如b、d转换成对应的ASCII字节),而是要把每两个十六进制字符转换成一个字节。可以用Java代码实现这个转换:

public static byte[] hexStringToByteArray(String hex) {
    int len = hex.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                             + Character.digit(hex.charAt(i+1), 16));
    }
    return data;
}

3. 分割多个序列化对象

Java序列化的每个对象都以魔数AC ED 00 05(十六进制)开头,你可以在转换后的字节数组中查找这个字节序列,以此分割出每个独立的序列化对象。

具体做法:遍历字节数组,每当找到连续的0xAC, 0xED, 0x00, 0x05时,标记一个新对象的开始位置,直到下一个魔数出现或者数组结束。

4. 解析每个序列化对象

对于每个分割出来的字节数组,使用ObjectInputStream来解析:

public static Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
    try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
         ObjectInputStream ois = new ObjectInputStream(bais)) {
        return ois.readObject();
    }
}

常见问题排查

  • 确保十六进制字符串长度是偶数:xxd -p输出的每个字节对应两个十六进制字符,若总长度为奇数,说明数据有丢失或篡改。
  • 如果分割后某个对象仍解析报错,可能是该对象的序列化数据不完整,或者不是标准的Java序列化对象(比如自定义了序列化逻辑)。

内容的提问来源于stack exchange,提问作者Nikita Jerschow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:34:37