Spark SQL运行报错NoClassDefFoundError: org.codehaus.janino.InternalCompilerException
问题根因
你遇到的异常本质是Janino依赖版本和Spark版本不兼容,加上直接执行java -jar时缺失运行时依赖导致的:
- Spark 2.4.3 官方默认绑定的Janino版本为3.0.8,你手动指定的3.0.16版本和Spark 2.4.3的代码不兼容,类结构发生了变化,因此抛出
NoClassDefFoundError。 - 直接运行
java -jar需要把所有依赖打进jar包(即fat jar/uber jar),如果只打包了业务代码,缺失Spark、Janino等依赖也会触发类找不到的错误。
具体解决方案
1. 修正依赖配置
删除手动引入的Janino依赖,不要排除Spark自带的Janino包,直接使用Spark默认配套的版本即可,修正后的Gradle配置如下:
implementation 'org.apache.spark:spark-sql_2.12:2.4.3' // 删掉手动引入的janino、commons-compiler依赖,也不要排除spark自带的janino
2. 配置Gradle打Fat Jar
添加shadow插件配置,把所有运行时依赖打进最终的jar包,示例配置如下:
plugins { id 'java' id 'com.github.johnrengelman.shadow' version '7.1.2' } group 'com.example' version '1.0-SNAPSHOT' repositories { mavenCentral() } dependencies { implementation 'org.apache.spark:spark-sql_2.12:2.4.3' } shadowJar { mergeServiceFiles() // 处理Spark的服务注册文件 exclude 'META-INF/*.DSA' exclude 'META-INF/*.RSA' exclude 'META-INF/*.SF' }
后续执行gradle shadowJar命令生成带依赖的jar包,再执行java -jar 生成的shadow jar包即可。
3. 优化SparkSession初始化代码
你当前的SparkSession创建方式存在冗余,不需要先初始化JavaSparkContext再转,直接用builder配置即可,避免上下文冲突:
SparkConf sparkConf = new SparkConf().setAppName("App demo").setMaster("local[*]"); try (SparkSession sparkSession = SparkSession.builder() .config(sparkConf) .getOrCreate()) { Dataset<Row> df = sparkSession.read().json("/Users/shubhampr/Documents/spark/examples/src/main/resources/people.json"); df.show(); } catch (Exception e) { log.error("Error in processing file: {}", e.getMessage(), e); // 建议打印完整堆栈,方便排查问题 return; }
可选方案(如果必须使用高版本Janino)
如果你的业务场景必须使用3.0.16版本的Janino,需要把Spark版本升级到3.0+,Spark 3.0及以上版本才适配了更高版本的Janino,升级Spark后再手动指定对应版本的Janino依赖即可。
内容的提问来源于stack exchange,提问作者Prashant Shubham
相关产品推荐
相关产品推荐

