You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark3.4.1+Java17单元测试加VM参数仍报错求助

Spark 3.4.1单元测试抛出ExceptionInInitializerError/IllegalAccessError的排查方案

问题场景

  • 运行环境:Java 17(corretto-17)、Gradle 7.3.3、Scala 2.12.17、IntelliJ IDEA、Spark 3.4.1
  • 触发错误:执行Spark单元测试时抛出ExceptionInInitializerError,底层堆栈指向IllegalAccessError,提示org.apache.spark.storage.StorageUtils$无法访问sun.nio.ch.DirectBuffer
  • 已尝试操作:在IntelliJ运行配置及build.gradle中添加VM参数,测试类通过SparkSessionTestWrapper初始化SparkSession;本地连接公司VPN,怀疑该环境因素影响

核心原因

该错误本质是Java 9+模块系统限制了对sun.nio.ch.DirectBuffer这类内部API的访问,Spark 3.x处理堆外内存时依赖该类,而Java 17的默认访问限制比低版本更严格。


排查与修复步骤

1. 确认VM参数配置的正确性与生效性

虽然已添加VM参数,但需确保参数格式正确且实际生效:

  • 必须添加的VM参数:
    --add-opens java.base/sun.nio.ch=ALL-UNNAMED
    --add-opens java.base/java.nio=ALL-UNNAMED
    --add-opens java.base/java.lang=ALL-UNNAMED
    
  • 验证参数是否生效:
    在测试类中添加代码打印当前JVM参数,运行后检查输出:
    System.out.println("VM Args: " + String.join(" ", ManagementFactory.getRuntimeMXBean().getInputArguments()));
    
    若未看到上述--add-opens参数,说明配置未生效:
    • IntelliJ端:确保在当前测试类的运行配置的VM options中添加参数,而非全局配置;
    • Gradle端:在build.gradle中明确配置测试任务的JVM参数:
      test {
          jvmArgs = [
              '--add-opens', 'java.base/sun.nio.ch=ALL-UNNAMED',
              '--add-opens', 'java.base/java.nio=ALL-UNNAMED',
              '--add-opens', 'java.base/java.lang=ALL-UNNAMED'
          ]
      }
      

2. 排查VPN环境的影响

VPN可能修改JVM运行环境或拦截本地通信,尝试以下操作:

  • 断开VPN后重新运行测试,验证是否恢复正常;
  • 若断开VPN后正常,检查VPN是否修改了JAVA_HOME等系统环境变量、添加了代理JVM参数,或拦截了Spark本地模式的内部通信;
  • 在VPN环境下,强制Spark使用本地回环地址初始化:
    在SparkSessionTestWrapper的初始化代码中添加配置:
    override val spark: SparkSession = SparkSession.builder()
        .master("local[*]")
        .appName("UnitTest")
        .config("spark.driver.host", "127.0.0.1")
        .config("spark.driver.bindAddress", "127.0.0.1")
        .getOrCreate()
    

3. 修复IntelliJ与Gradle的同步问题

  • 执行File -> Sync Project with Gradle Files,确保Gradle配置同步到IDE;
  • 尝试用Gradle命令行直接运行测试:./gradlew test --tests "你的测试类全路径",若命令行运行正常但IDE异常,删除现有测试运行配置后重新创建。

4. 清理依赖缓存与排查冲突

  • 清理Gradle缓存并重新构建:./gradlew clean build --no-build-cache;
  • 检查依赖冲突:在build.gradle中添加依赖分析任务,查看是否混入旧版本Spark或Java相关依赖:
    task checkDependencies {
        doLast {
            configurations.compileClasspath.each { println it }
        }
    }
    
    运行./gradlew checkDependencies,排查版本不符的依赖。

内容的提问来源于stack exchange,提问作者ChewyLime4

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 13:53:20