大家好,我想了解您对我们在一些 Spark 作业中尝试使用 Java 序列化来序列化 protobuf 时遇到的问题的看法(似乎其他人也遇到了同样 的 问题)。我在这里放置了一个示例堆栈跟踪。该错误一开始很令人困惑,但查看GenevedMessageLite中的相关行我想我看到了问题:https://github.com/google/protobuf/blob/774d630bde574f5fcbb6dae6eaa0f91f7bc12967/java/src/main/java/com/google/ protobuf/GenerateMessageLite.java#L768
对 的调用Class.forName
不包含ClassLoader
参数,因此它将尝试使用ClassLoader
用于加载 的 任何一个GeneratedMessageLite
。由于 Spark 本身使用 protobuf-java,因此这最终成为ClassLoader
链的更上游,它对我们的 protobuf 类一无所知。为了确认这就是问题所在,我们在 Spark 执行器中运行了以下代码:
// fails with ClassNotFoundException
Class.forName("com.hubspot.Protos$ExampleProto", true, GeneratedMessageLite.class.getClassLoader());
// works fine
Class.forName("com.hubspot.Protos$ExampleProto", true, Thread.currentThread().getContextClassLoader());
Spark 案例中有一些解决方法,但这似乎是一个更普遍的问题,可能会在 Spark 之外出现。是否考虑切换 的所有用法以Class.forName
包含显式ClassLoader
参数?这样,可以优先考虑线程的上下文类加载器,类似于Guava 中的 Resources 类使用的策略
我很想听听您对这个问题的看法,谢谢