PySpark集成Apache Arrow报错:sun.misc.Unsafe/DirectByteBuffer不可用
问题解决:PySpark集成Apache Arrow时出现sun.misc.Unsafe/DirectByteBuffer异常
问题概述
使用PySpark 3.4、Apache Arrow 1.5和JDK 21时,执行toPandas()或Arrow相关操作时抛出以下异常:
java.lang.UnsupportedOperationException: sun.misc.Unsafe or java.nio.DirectByteBuffer.
(long, int) not available
at org.apache.arrow.memory.util.MemoryUtil.directBuffer(MemoryUtil.java:174)
at org.apache.arrow.memory.ArrowBuf.getDirectBuffer(ArrowBuf.java:229)
根本原因
- JDK权限限制:JDK 9及以后逐步收紧了对
sun.misc.Unsafe等内部API的反射访问权限,JDK 21进一步限制了这类操作,而旧版本Arrow(如1.5)依赖这些内部API实现内存管理。 - 版本兼容性不匹配:Apache Arrow 1.5发布于2020年,完全不支持JDK 21;同时Spark 3.4官方推荐的Arrow版本为12.0.0,1.5版本与Spark 3.4存在严重的兼容性冲突。
解决方案
1. 升级Apache Arrow版本
将Arrow版本升级至15.0.0及以上(该版本开始完善对JDK 21的支持),同时确保与Spark 3.4兼容(Spark 3.4支持Arrow 10.x-15.x版本)。
2. 添加JVM权限参数
在Spark启动时添加JVM参数,允许访问被限制的内部API,可通过代码修改或提交命令配置:
修改PySpark代码中的SparkSession构建
import os import pandas as pd from pyspark.sql import SparkSession spark = SparkSession.builder \ .appName("ArrowPySparkExample") \ .config("spark.driver.extraJavaOptions", "--add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/sun.misc=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED") \ .config("spark.executor.extraJavaOptions", "--add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/sun.misc=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED") \ .getOrCreate() spark.conf.set("spark.sql.execution.arrow.pyspark.enabled", "true") pdf = pd.DataFrame(["midhun"]) df = spark.createDataFrame(pdf) result_pdf = df.select("*").toPandas()
或通过spark-submit命令添加参数
spark-submit --conf spark.driver.extraJavaOptions="--add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/sun.misc=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED" --conf spark.executor.extraJavaOptions="--add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/sun.misc=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED" your_script.py
3. 验证环境一致性
- 确保Python环境中的
pyarrow版本与Java端的Arrow版本一致,避免跨版本不兼容:pip install pyarrow==15.0.0 - 检查
JAVA_HOME环境变量是否指向JDK 21的安装路径,确保Spark使用正确的JDK版本。
关键说明
- 优先选择升级Arrow版本,而非仅依赖JVM参数,旧版本Arrow在JDK 21下可能存在其他未暴露的兼容性问题。
- 严格遵循Spark官方文档中各Spark版本对应的推荐Arrow版本,避免版本不匹配引发的异常。
内容的提问来源于stack exchange,提问作者Midhun Pottammal
相关产品推荐
相关产品推荐

