Scala的序列化,Serialization以及SerialVersionUID

Java serialVersionUID 作用和自动生成设置 军工项目代码提交后,审查代码漏洞,序列化经常被忽视 阅读详情

Problem

序列化一个Scala对象为文本或者二进制数据,以便支持持久化或者网络传输等需求,并通过读取这些数据,可以反序列化出这个对象

Feature requests

  • easy to use
  • 支持自定义序列化(如部分member)
  • 尽可能的编译期检查
  • Schema Evolution?

Key metrics

  • 序列化/反序列化 速度
  • 序列化数据 空间占用
  • 通用性

Solution

  • extend or mixin Serializable trait

scala Serializable 实际上就是一个java.io.Serializable的universal trait

package scala

/**
 * Classes extending this trait are serializable across platforms (Java, .NET).
 */
trait Serializable extends Any with java.io.Serializable

@SerialVersionUID

class Foo extends Serializable {
  // class code here
}

Static annotation SerialVersionUID可以与Serialization一起使用

If no serialVersionUID is declared, JVM will use its own algorithm to generate a default SerialVersionUID.

When to specify SerialVersionUID?

SerialVersionUID的目的是为了检查序列化和反序列化的类是否兼容。

  • 第一种情况,序列化的目的只是为了在网络上即时传输,如rpc, mq等,或者在实现上考虑,为了节省内存,只保存序列化之后的对象,如spark cache等,一般来说可以不显式指定SerialVersionUID
  • 第二种情况,需要直接使用序列化来持久化对象,如将训练好的模型存储到文件系统上,就最好指定SerialVersionUID,且当类不向前兼容的时候,应该重新生成SerialVersionUID
  • 第三种情况,如果对各编译器,不同的JVM 兼容性要求很高,如Java™ Object Serialization Specification建议,应当给每个序列化类都指定SerialVersionUID

按需序列化一部分对象?

当一个类mixin Serializable 之后,整个类的实例(all members)都会被序列化,但有时候这并不是我们需要的

  • 对象持有非常大的member,序列化和反序列化的开销很大,而我们并不需要序列化它
  • 业务逻辑中,大量序列化和反序列化的开销成为瓶颈,需要优化
  • 对象member不可/难以序列化,如网络连接,数据流等,或者是引用第三方库中不可序列化的对象

Solution 1: hygienic closure

  • 通过closure来避免序列化整个实例, 而是根据需要传参
def closureFunction[E,D,R](enclosed: E)(gen: E => (D => R)) = gen(enclosed)

class Foo {
  val v1 = 42
  val v2 = 73
  val n = new NotSerializable

  // use shim function to enclose *only* the values of 'v1' and 'v2'
  def f() = closureFunction((v1, v2)) { enclosed =>
    val (v1, v2) = enclosed
    (x: Int) => (v1 + v2) * x   // Desired function, with 'v1' and 'v2' enclosed
  }
}
new Foo.f
  • auto nulling via closure cleaning 闭包清理
    由于 spark 大量使用closure serialization, 当一个closure 包含了一些在闭包函数中不必要的引用时(Scala issue: SI-1419, fixed in 2.12),就会浪费网络传输带宽,CPU 开销,还有可能引入一些不可被序列化的对象,导致整个闭包无法序列化。
    spark 中使用 ClousureCleaner 在运行时遍历对象,可以更精确的排除不必要的引用。

Solution 2: @transient lazy

Static annotation @transient 表示修饰的 member 不需要被序列化
比如一个 SparkJob base class


class SparkJob(args: Args) extends Serializable {
  @transient
  protected lazy val sparkConf = new SparkConf()

  @transient
  protected lazy val sc = new SparkContext(sparkConf)
  
  ...
}

由于引用的sparkConf, sparkContext都是不可序列化的,
且都不需要被传送到executor上运行,因此可以用@transient表示该成员不需要被序列化

再如,一个算法模型类,需要读取模型文件,并且需要频繁通过ByteBuffer来操作二进制数据
但是ByteBuffer本身又是不可序列化的, 此时可以使用 @transient (private) lazy pattern
其中 @trainsient 可以避免 overhead,lazy 可以第一次被调用时正确地初始化以避免NPE

class Model(
  val model: Array[Byte],
  val offset: Array[Byte]
) extends Serializable {

  @transient private lazy val offsetBuffer = ByteBuffer.wrap(offset).order(ByteOrder.LITTLE_ENDIAN)
  @transient private lazy val modelBuffer  = ByteBuffer.wrap(model).order(ByteOrder.LITTLE_ENDIAN)
  ... 
}

这种模式也适用于其他难以被序列化的 member,比如数据库连接,IO stream 等,每个实例只需序列化可以用来重建这些 member 的元信息即可。

Spark 序列化与性能

在如 Spark 这样的分布式计算框架中, broadcast, shuffle, action等操作都会使得对象被序列化。使每个被闭包捕获的变量都可序列化,可以避免异常,但是变量非常大时,容易影响性能,以及有可能造成内存泄露。

Solution 1: Kryo(chill)

在 Spark 中使用 kryo serializer 来获得更小的序列化开销

val conf = new SparkConf().setMaster(...).setAppName(...)
conf.registerKryoClasses(Array(classOf[MyClass1], classOf[MyClass2]))
val sc = new SparkContext(conf)

Solution 2: Broadcast

在 Spark 中如果通过闭包引用了一个huge object, 那么这个object会被至少序列化 numPartitions 次,而如果使用broadcast variables, 那么只会被序列化 numNodes 次,通常 numPartitions > numNodes

References

http://erikerlandson.github.io/blog/2015/03/31/hygienic-closures-for-scala-function-serialization
https://github.com/samthebest/dump/blob/master/sams-scala-tutorial/serialization-exceptions-and-memory-leaks-no-ws.md
http://stackoverflow.com/questions/285793/what-is-a-serialversionuid-and-why-should-i-use-it

Scala编程中的序列化与反序列化 无论是Java序列化、JSON序列化还是ProtoBuf序列化,都可以根据具体情况选择最适合的方法来实现对象的序列化和反序列化操作。序列化和反序列化是在编程中常用的概念,用于将对象转换为字节流以便存储或传输,并且能够重新构造出相同的对象。本文将介绍一些常见的序列化和反序列化技术,并提供相应的Scala代码示例。JSON是一种常用的数据交换格式,Scala中有多个库可以用于JSON序列化和反序列化,例如。然后,我们从文件中反序列化对象,并打印出反序列化得到的对象。在上面的示例中,我们定义了一个可序列化的。 阅读详情

相关推荐

平衡电桥在高压绝缘检测中的动态切换策略与误差优化

本文深入探讨了平衡电桥在高压绝缘检测中的动态切换策略与误差优化方法。通过分析四种基本切换模式及智能切换时序设计,显著提升检测精度与范围。结合电阻选型黄金法则和软件补偿技术,有效降低测量误差,为电动汽车电池管理系统提供可靠的安全保障。

weixin_30275415的博客 473

serialVersionUID 问题处理

serialVersionUID 问题处理Serializable 和 Externalizabletransient什么是serialVersionUID建议 Serializable 和 Externalizable 类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法进行序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。 查看Serializable接口的源代码可以看到接口是空的,没有任何的方法或字段,仅用于标示可序列化的语义,如果一个类没有实

csdn565973850的博客 2200

开关电源环路学习笔记(1)-为啥要知道传递函数?

做硬件都会接触到开关电源,或多或少会接触到环路补偿。很多兄弟们也提出来让我说说这个,说明大家也都很关心,也说明这个好像有点难。 就我个人而言,我也想搞明白环路这一块,也查了一些资料,视频,不过说实话,一直都还是懵的,感觉很困难。 具体感觉就是,看资料或视频的时候,感觉好像是那么回事。但是撇开之后,就又云里雾里的感觉,总有一些想法没有找到答案。 问题 比如下面我想过的问题: 开关电源有开关,根本就不是一个线性系统,传递函数是咋弄出来的? 系统环路框图的输入量为什么不是Vin,而是参考电压V

weixin_42005993的博客 1万+

IDEA使用笔记(八)——自动生成 serialVersionUID 的设置

这个设置比较简单,也有一些博文已经写到了,为什么我还要写哪?(潜台词:因为我想凑一篇博文)我觉得学习,特别是编程学习是需要重复造轮子的,另外,就是加深自己的印象方便自己的查找。还有就是关键点,有些博客没有重点强调到位,比如:为什么要设置这玩意?这个下一篇博文再分析,还有就是设置的时候的注意细节(添加serialVersionUID 的时候,先选中对应的类名,然后按 alt+enter 快捷键)没有...

weixin_34234823的博客 537

GitLab教程(四):分支(branch)和合并(merge)

命令进行合并时,Git具备一定的智能自动化处理能力:如果一个分支仅修改了文件A,而另一个分支独立地修改了文件B,Git能够无缝整合这些更改,自动完成合并过程——即最终的代码既包含了对A文件的修改也包含了对B文件的修改。同样地,若两个分支虽然都修改了同一个文件,但涉及的是文件中互不重叠的部分,比如一个改动发生在第一行,另一个则在第二行,Git同样能巧妙地自动合并这些非冲突性修改。获取了远程分支的最新变化,或者当你想要合并本地的一个分支到当前分支时,就会用到这个命令。,默认会尝试合并远程分支到当前分支。

TracyCoder的博客 7885

软件测试工程师最常用的Linux系统命令大全(汇总)

cd命令这是一个非常基本,也是大家经常需要使用的命令,它用于切换当前目录,它的参数是要切换到的目录的路径,可以是绝对路径,也可以是相对路径。

1330

serialVersionUID-反序列化异常

设置serialVersionUID 后,序列化和反序列化的时候不会因为对象修改后的serialVersionUID 不同而导致异常,若使用过缓存依然要及时清理缓存。即将结果出参类LiveRankVO设置进了缓存,且,后续更新代码时,该出参类LiveRankVO被修改,但是缓存中依然是修改前的旧对象。将缓存中的旧对象数据清除后,重新缓存进去。(也是本人当时解决的办法),建议还是要规范实体类实现序列化,增加。固定的serialVersionUID,以免出错。当然也可不增加,但是要注意对象放入缓存中的使用。

h_970918的博客 662

修改yolov8使支持单通道图像输入

默认支持BGR三通道图像输入,但是在很多工业场景下,存在很多灰度图像的场景,因此对yolov8代码做一些修改以支持单通道图像输入,满足项目实际需求。训练时,只需要在 data 的 yaml 文件中,添加 ch=1 即可。

mingo_敏 5779

Java序列化机制详解与最佳实践

序列化是将对象转换为可存储或传输格式的基础技术,其核心原理是通过字节流表示对象状态。Java通过Serializable接口实现原生序列化,利用serialVersionUID进行版本控制。这项技术在分布式系统、持久化存储和跨进程通信中具有重要价值,特别是在微服务架构中,高效的序列化方案能显著提升系统性能。针对安全性和性能优化,开发者需要注意transient字段处理、自定义序列化逻辑以及替代方案选择。热门的序列化框架如Protocol Buffers和Kryo在特定场景下相比Java原生序列化能带来显著的

weixin_34377919的博客 357

fasterlio原理及代码框架梳理

Faster-LIO 的优势是在保持同等高精度的前提下,显著提升计算效率,以支持更极端的应用场景(如高速无人机)和更廉价的硬件平台。可以把 Faster-LIO 理解为用一把更快的“空间哈希筛子”(iVox)替换了原来精细的“动态平衡树”(ikd-Tree),从而在精度损失极小的情况下,实现了效率的显著提升。:只在实际有地图点的空间区域动态创建和保留体素单元,形成一个稀疏的体素地图。是关键:将去畸变点云中的每个点,在 iVox 维护的局部地图中搜索近邻(如5个最近点),构建点到面的距离残差。

Studying…… 246

基于 MFC C++ 的心电监测客户端

4. **报警功能**:使用 `PlaySound` 播放报警音(需准备 `alert.wav` 文件),界面显示报警状态。

寒寒豆豆软件公司的博客 92

idea 添加serialVersionUID提示

idea添加 serialVersionUID提示

寂夜了无痕的博客 5007

华为OD机试真题 新系统 2026-09-26 Java&Go&C【数据中心最佳维护时间窗】

数据中心使用一个整数数组 scores,记录 N 小时内每小时的服务器得分(可正可负)。0 表示服务器故障(无效小时)。

MISAYAONE的博客 100

java的序列化注解Serial、序列化版本号serialVersionUID、eclipse中自动生成serialVersionUID

java的序列化注解Serial、序列化版本号serialVersionUID、eclipse中自动生成serialVersionUID

听海边涛声 6531

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

IDEA上代码注释模板设置、serialVersionUID自动生成设置、git提交项目时忽略无用文件、字符编码UTF8设置、注解生效激活设置、Java编译版本设置

IDEA上git提交项目时忽略无用文件、开发时常用的文件代码模板设置、字符编码UTF8设置、注解生效激活设置、Java编译版本设置、serialVersionUID自动生成设置

Da_zhenzai的博客 1万+

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

scala 序列化

匿名函数和object对象方法 都具备序列化能力,而类默认是没有的。

seaReal1的博客 2364

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

serialVersionUID的重要性,及Idea自动生成 serialVersionUID的设置

介绍serialVersionUID的重要性,及Idea自动生成 serialVersionUID的设置

拾年一剑 的专栏 2335

【转】JSON教程

JSON 是什么? JSON 的全称是JavaScript Object Notation,是一种轻量级的数据交换格式。JSO N 与XML 具有相同的特性,例如易于人编写和阅读,易于机器生成和解析。但是JSON 比 XML 数据传输的有效性要高出很多。JSON 完全独立与编程语言,使用文本格式保存。 JSON 数据有两种结构: • Name-Value 对构成的集合,类似于Java 中...

weixin_30707875的博客 245

【scala】为什么要实现Serializable

最近在看scala写的代码,一个使用scala语言写的,获取大量样本用于模型迭代。这里的主类是Serializable 的implements,突然间不知道什么是Serializable了,搜索相关资料汇总与此,不断完善更新ing。 首先说明Serializable主要作用将类的实例持久化保存,序列化就是保存,反序列化就是读取。保存也不一定保存在本地,也可以保存到远方。类一定要实现Seria...

凝眸伏笔的博客 3342

scala 序列化SerialVersionUID

scala 序列化需要继承自Serializable 这个特质 SerialVersionUID 的写法为: @SerialVersionUID(-4486938584926174252L)//使用注解来制定序列化id class XXX extends Serializable{ } 作者:yc… 来源:优快云 原文:https://blog.csdn.net/tingibandequ/art...

履霜寒冰至 1500

scala类的序列化_Scala序列理解,通用类和内部类示例

scala类的序列化A sequence comprehension statement consists of a generator part which generates a list of values from the specified range of inputs and a statement which operates on these generated elements...

从零开始的教程世界 2261

实体类序列化 serialVersionUID 告警设置

在下图文件中设置 ,在新建实体类中若没有serialVersionUID 会做出提示

bingguang1993的博客 453

idea中出现java.lang.UnsupportedClassVersionError: scala/Serializable的原因

java.lang.UnsupportedClassVersionError: scala/Serializable

Laoddaaa的博客 1320

使用IntelliJ IDEA自动生成serialVersionUID

实体对象实现了java.io.Serializable接口后,一般都会提供一个serialVersionUID以做版本区分。在idea里,可以通过设置来快速生成serialVersionUID。 设置方法 1、打开Preferences–>Editor–>Inspections,然后在右侧输入UID进行搜索(搜索方式比较快,也可以在java–>Serialization issues里找)。然后勾选Serializable class without 'serialVersionUID

766

关于serialVersionUID的作用解释说明

serialVersionUID 是用于在序列化和反序列化过程中进行核验的一个版本号。

记录分享编程与冲浪知识 3837

JDK 序列化, 碰到 serialVersionUID 不一致问题,怎么处理?

点击下方“IT牧场”,选择“设为星标”公司有个子服务较多,交互频繁的系统,有一些需要共享传输的对象,它们通过 JDK 序列化(Java Object Serialization)后进行交互...

ITMuch的专栏 891
上一篇: Docker desktop使用配置
下一篇: scala 加载properties文件
Code_LT
博客等级 码龄10年 307粉丝 182原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值