应使用 System.nanoTime() 精确测量序列化/反序列化耗时,区分单次耗时与统计趋势,捕获异常类型辅助排查;需预热、避免 IO 干扰、按业务数据抽样,并封装工具方法统一计时、异常处理与结构化上报。

直接在序列化和反序列化操作前后记录系统纳秒时间,相减即可得到精确耗时。关键不是“能不能测”,而是测得准、留得下、看得清——尤其要区分单次耗时与统计趋势,还要捕获异常类型辅助排查。
用 System.nanoTime() 获取高精度耗时
相比 currentTimeMillis(),System.nanoTime() 不受系统时钟调整影响,分辨率更高,适合测量短时操作(如一次序列化)。注意它返回的是纳秒值,建议转为毫秒或微秒展示更直观。
- 序列化耗时:开始前调用
nanoTime(),writeObject() 完成后立刻再调一次,差值即为耗时 - 反序列化同理:readObject() 前后各记一次,注意必须在成功获取对象后才计算(避免把 ClassNotFoundException 等异常耗时混入)
- 示例片段:
long start = System.nanoTime(); try (ObjectOutputStream oos = new ObjectOutputStream(...)) { oos.writeObject(obj); } long durationNs = System.nanoTime() - start; log.info("serialize {} took {} μs", obj.getClass().getSimpleName(), TimeUnit.NANOSECONDS.toMicros(durationNs));
结合日志与监控埋点统一记录
单纯打印日志不够,工程中建议将耗时和异常封装为结构化事件上报。比如用 SLF4J 打点 + MDC 补充上下文,或接入 Micrometer / Prometheus 做聚合监控。
- 记录字段至少包含:操作类型(serialize / deserialize)、类名、耗时(ms)、是否成功、异常类名(如 IOException、ClassNotFoundException)
- 对高频调用(如缓存读写),可采样记录(例如仅记录 P95 耗时超阈值的请求)
- 异常类型特别重要:ClassNotFoundException 说明类缺失,InvalidClassException 多因 serialVersionUID 不匹配,IOException 可能是磁盘或流问题——不同异常对应不同排查路径
避免常见干扰项
测出来的数字不准,往往不是代码问题,而是环境或方式干扰:
立即学习“Java免费学习笔记(深入)”;
- 不要在首次调用时测:JVM 类加载、JIT 编译会影响首几次性能,建议预热 10–100 次后再正式采集
- 关闭无关 IO 干扰:避免 FileOutputStream 写到机械硬盘或网络文件系统;本地测试优先用 ByteArrayOutputStream / ByteArrayInputStream
- 注意对象大小波动:同一个类的不同实例序列化耗时可能差数倍(如 String 字段长度差异大),建议按实际业务数据分布抽样,而非只测空对象
封装工具方法便于复用
把计时、异常捕获、日志格式统一收口,避免每个地方重复写 try-catch 和 time 计算:
- 提供泛型工具方法,例如:
<T> T measureDeserialize(String name, Supplier<T> action) - 内部自动记录耗时、捕获并分类异常、输出结构化日志
- 配合配置开关,线上可动态开启/关闭耗时采集,避免性能损耗



















