PAYATHON 2026

升级 Spark 4.0 后找不到 MemoryStream,是包路径变更还是已弃用?

数据小陈

结论

MemoryStream 在 Apache Spark 4.0.0 中仍然存在,包名仍是 org.apache.spark.sql.execution.streaming。该版本源码中的类声明没有标记 @deprecated,不能根据这次 cannot find symbol 错误认定它已被弃用或删除。Spark 4.0.0 源码

如果项目实际使用的是官方 Spark 4.0.0,应先检查测试编译依赖,确认所用 JAR 中的包路径已经变化后再修改 import。问题没有提供依赖清单,目前无法确定实际加载了哪个版本。

为什么不能直接改成 runtime 包?

Spark 后续确实重组了 streaming 目录,相关任务 SPARK-52787 的修复版本是 4.1.0。但源码文件目录发生变化,并不一定意味着 Scala 文件中的 package 声明也发生了变化,相关 PR 的讨论明确指出了这一点。SPARK-52787、目录重组 PR

因此,不能从 runtime/memory.scala 这个文件路径推断 Spark 4.0.0 必须使用 runtime.MemoryStream。

如何排查并修改?

1. 确认测试编译时使用的依赖

如果使用 Maven,可以查看依赖树:

mvn dependency:tree -Dincludes=org.apache.spark:*,org.scala-lang:*

重点检查:

  • 测试编译类路径中是否包含 spark-sql。
  • Spark 各模块是否使用一致的版本。
  • 是否存在旧依赖或传递依赖,导致实际解析版本与升级目标不同。
  • Scala 二进制版本后缀是否一致。

检查构建工具实际解析出的依赖,不要只看配置文件里声明的目标版本。

2. 检查实际 JAR 中的类路径

将下面的路径替换为测试编译使用的 spark-sql JAR:

jar tf /path/to/spark-sql.jar | grep 'MemoryStream'

如果 JAR 中包含:

org/apache/spark/sql/execution/streaming/MemoryStream.class

应保留原来的导入:

import org.apache.spark.sql.execution.streaming.MemoryStream;

如果实际包含的是:

org/apache/spark/sql/execution/streaming/runtime/MemoryStream.class

则针对该依赖使用:

import org.apache.spark.sql.execution.streaming.runtime.MemoryStream;

如果两者都不存在,继续检查 JAR 是否正确、是否进入测试编译类路径,以及是否使用了定制发行包。检查结果只能确认本地依赖的内容,不能概括所有 Spark 版本的行为。

3. 重新编译,再处理后续兼容性错误

先解决 import 处的错误。后面的 MemoryStream inputStream 无法解析,可能只是同一问题的连带结果。

找到类之后,如果构造函数、ExpressionEncoder.apply(TRANSFORM_SCHEMA) 或 Scala 集合转换又出现错误,再根据实际版本逐项调整。建议将原始类型声明改为:

MemoryStream<Row> inputStream;

这有助于保留泛型信息,但不能解决类路径问题。由于缺少 TRANSFORM_SCHEMA、依赖清单和测试环境,不能保证原片段只修改 import 就能完整编译。

是否需要替代 MemoryStream?

单元测试需要手动调用 addData 注入微批次时,可以继续考虑 MemoryStream。它属于 Spark 内部实现,源码明确说明它用于测试,不宜依赖其跨版本接口稳定性。MemoryStream 实现与用途说明

替代方式取决于测试目标:

  • 只验证 DataFrame 转换逻辑:使用 spark.createDataFrame(rows, TRANSFORM_SCHEMA) 构造静态输入,并将转换逻辑提取为可独立调用的方法。
  • 需要验证流查询行为:可以使用临时目录中的文件作为流输入,通过 readStream.schema(...).json(...) 等接口读取,并分批加入测试文件。

静态 DataFrame 适合验证字段转换、过滤和计算结果;涉及 watermark、状态或流查询执行的测试仍需要流式输入。

备注:内容仅供参考。