Spark SQL失败,因为“常量池已超过JVM限制0xFFFF”

我在EMR 4.6.0 + Spark 1.6.1上运行此代码:

val sqlContext = SQLContext.getOrCreate(sc) val inputRDD = sqlContext.read.json(input) try { inputRDD.filter("`first_field` is not null OR `second_field` is not null").toJSON.coalesce(10).saveAsTextFile(output) logger.info("DONE!") } catch { case e : Throwable => logger.error("ERROR" + e.getMessage) } 

saveAsTextFile的最后一个阶段,它失败并显示以下错误:

 16/07/15 08:27:45 ERROR codegen.GenerateUnsafeProjection: failed to compile: org.codehaus.janino.JaninoRuntimeException: Constant pool has grown past JVM limit of 0xFFFF /* 001 */ /* 002 */ public java.lang.Object generate(org.apache.spark.sql.catalyst.expressions.Expression[] exprs) { /* 003 */ return new SpecificUnsafeProjection(exprs); /* 004 */ } (...) 

可能是什么原因? 谢谢

这是因为已知的Java限制使生成的类超过64Kb。

这个限制已经在SPARK-18016中得到解决,它在Spark 2.3中得到修复 – 将于2018年1月发布。

通过删除Dataframe中所有未使用的列或仅过滤实际需要的列来解决此问题。

Turnes Out Spark Dataframe无法处理超宽模式。 Spark可能会破坏特定数量的列“常量池已超过JVM限制0xFFFF” – 这取决于查询的类型,但减少列数可以帮助解决此问题。

根本原因在于JVM为生成的Java类提供了64kb – 另请参阅Andrew的答案。

为了将来参考,这个问题在spark 2.3得到了解决(正如Andrew所说)。

如果您在Amazon EMR上遇到此问题,请升级到5.13或更高版本。