java对象网络传输需先序列化为字节流再发送,接收端反序列化还原;必须实现serializable接口并建议显式声明serialversionuid,transient字段不参与序列化;原生方式用objectoutputstream/objectinputstream封装socket流,但存在性能低、不跨语言、反序列化安全风险等问题,生产环境推荐json/http、grpc或netty+kryo等替代方案。

Java 中对象通过网络传输,核心是先序列化成字节流,再经 Socket 或网络框架发送;接收端反序列化还原对象。关键不在“能不能传”,而在于“怎么传得安全、兼容、高效”。
必须实现 Serializable 接口
要让一个类能被序列化,它和所有非 transient 成员变量所属的类,都得实现 java.io.Serializable 接口。这不是个普通接口——它没有方法,纯粹是给 JVM 的标记。
- 不加这个接口,调用
ObjectOutputStream.writeObject()会直接抛NotSerializableException - 建议显式声明
serialVersionUID(如private static final long serialVersionUID = 1L;),避免因类结构微调导致反序列化失败 - 用
transient修饰的字段不会参与序列化,适合存密码、临时计算结果等敏感或非持久数据
用 ObjectOutputStream / ObjectInputStream 封装 Socket 流
原生方式最直接:把 Socket 的输入输出流,包一层对象流,就能读写对象。
- 发送端:创建
ObjectOutputStream包裹socket.getOutputStream(),调用writeObject(obj) - 接收端:用
ObjectInputStream包裹socket.getInputStream(),调用readObject()得到对象 - 注意:两端类路径、类版本、字段定义必须一致,否则反序列化时抛
ClassNotFoundException或InvalidClassException - 每次
writeObject后建议调用reset()(尤其在循环发送多个对象时),防止引用重复导致反序列化出错
实际项目中更推荐替代方案
Java 原生序列化虽简单,但存在严重短板:性能低、体积大、不跨语言、有反序列化漏洞风险(如 Apache Commons Collections 反序列化链)。生产环境普遍不用它直接走网络。
- HTTP + JSON:用 Jackson 或 Gson 把对象转成 JSON 字符串,通过 HTTP POST 发送,接收方再解析。兼容性好、调试方便、天然跨语言
- RPC 框架:如 Dubbo、gRPC,默认用 Protobuf 或 Hessian 等高效二进制协议,比 Java 原生序列化快 3–5 倍,且支持多语言
-
Netty 自定义编解码器:若需高性能 TCP 通信,可用 Netty 搭配自定义序列化器(如 Kryo、FST),避开
ObjectInputStream的性能瓶颈和安全限制
务必重视反序列化安全
从不可信来源(如公网请求)直接反序列化字节流,等于执行对方控制的代码逻辑,历史上引发过大量 RCE 漏洞。
- 永远不要对用户输入、网络响应等外部数据调用
ObjectInputStream.readObject() - 如必须用原生序列化,可通过重写
ObjectInputStream.resolveClass()白名单校验类名 - 优先选用有类型白名单机制的序列化库(如 Jackson 的
@JsonTypeInfo配合子类白名单)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











