objectinputstream通过jvm底层反射直接分配内存并填充字段,不调用任何构造方法;要求类结构完全一致、serialversionuid匹配才执行反射赋值;transient和static字段被主动跳过。

ObjectInputStream 依赖反射重建对象实例
ObjectInputStream 在反序列化时并不调用任何构造方法(包括无参构造器),而是直接通过 JVM 底层的反射机制,在不执行初始化逻辑的前提下分配内存并填充字段值。这个过程绕过了常规的对象创建流程,属于 JVM 特有的“非构造式实例化”——它利用了 sun.misc.Unsafe 或类似底层 API(不同 JDK 版本实现略有差异),配合类的私有字段访问权限放宽策略,完成字段值的逐个写入。
字段还原依赖类结构完全一致
反射能正确写入字段的前提是:运行时加载的类字节码与序列化时使用的**完全相同**。这包括:
- 全限定类名(包名 + 类名)必须一致,哪怕只是大小写差异也不行
- 所有非 transient 字段的名称、类型、声明顺序需严格匹配
- 父类是否实现 Serializable、是否有可访问的无参构造器,会影响父类字段能否被还原
- 若字段是引用类型,其对应类也必须在类路径中存在且结构兼容
一旦某字段在新版本中被删除、重命名或类型变更,反射将找不到目标字段,抛出 java.io.InvalidClassException 或静默跳过(取决于 JDK 版本和序列化兼容策略)。
serialVersionUID 是反射行为的“开关阀”
ObjectInputStream 在开始反射还原前,会先比对字节流中嵌入的 serialVersionUID 和当前类静态常量的值。这个比对不是为了“版本号语义”,而是作为反射操作是否继续的判定依据:
- 匹配 → 进入字段映射与反射赋值阶段
- 不匹配 → 直接中断,抛出 InvalidClassException,根本不会触发后续反射逻辑
注意:JVM 不会尝试“智能适配”字段差异,也不会用默认值填充缺失字段。它只做精确匹配后的批量反射写入。
transient 和 static 字段由反射机制主动跳过
ObjectInputStream 的反射逻辑内置了字段过滤规则:
- transient 字段:在序列化时就被跳过,字节流中不包含其数据;反序列化时反射自然不处理,保持默认值(如 null、0、false)
- static 字段:属于类而非实例,不在对象图中;反序列化时反射不触碰,维持当前类加载时的值
- 若需自定义 static 或 transient 字段的恢复逻辑,可通过实现 readObject() 方法,在其中手动调用反射或赋值
这种设计让反射行为既高效又可控,避免了对无关成员的误操作。











