升级 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、状态或流查询执行的测试仍需要流式输入。
备注:内容仅供参考。
