我有一个spark scala程序,它加载我在java中编写的jar。从该jar调用静态函数,该函数尝试从文件(Pattern.class
)读取序列化对象,但抛出java.lang.ClassNotFoundException
。
在本地运行spark程序可以正常工作,但在群集工作者上却没有。这特别奇怪,因为在我尝试从文件中读取之前,我实例化了一个Pattern
对象并且没有问题。
我确信我在文件中写的Pattern
个对象与我想要阅读的Pattern
个对象相同。
我检查了从机中的jar,Pattern
类就在那里。
有谁知道问题可能是什么?如果需要,我可以添加更多细节。
这是Pattern类
public class Pattern implements Serializable {
private static final long serialVersionUID = 588249593084959064L;
public static enum RelationPatternType {NONE, LEFT, RIGHT, BOTH};
RelationPatternType type;
String entity;
String pattern;
List<Token> tokens;
Relation relation = null;
public Pattern(RelationPatternType type, String entity, List<Token> tokens, Relation relation) {
this.type = type;
this.entity = entity;
this.tokens = tokens;
this.relation = relation;
if (this.tokens != null)
this.pattern = StringUtils.join(" ", this.tokens.toString());
}
}
我正在通过以下方式从S3读取文件:
AmazonS3 s3Client = new AmazonS3Client(credentials);
S3Object confidentPatternsObject = s3Client.getObject(new GetObjectRequest("xxx","confidentPatterns"));
objectData = confidentPatternsObject.getObjectContent();
ois = new ObjectInputStream(objectData);
confidentPatterns = (Map<Pattern, Tuple2<Integer, Integer>>) ois.readObject();
LE:我在运行时检查了类路径,并且jar的路径不存在。我为执行者添加了它,但我仍然遇到同样的问题。我不认为是这样,因为我在jar中调用了readObject函数的Pattern类。
答案 0 :(得分:1)
建议在添加这种方法之前在调用之前找出类路径资源,以确保从调用者的角度来看一切都很好
public static void printClassPathResources() {
final ClassLoader cl = ClassLoader.getSystemClassLoader();
final URL[] urls = ((URLClassLoader) cl).getURLs();
LOG.info("Print All Class path resources under currently running class");
for (final URL url : urls) {
LOG.info(url.getFile());
}
}
--conf "spark.driver.extraLibrayPath=$HADOOP_HOME/*:$HBASE_HOME/*:$HADOOP_HOME/lib/*:$HBASE_HOME/lib/htrace-core-3.1.0-incubating.jar:$HDFS_PATH/*:$SOLR_HOME/*:$SOLR_HOME/lib/*" \
--conf "spark.executor.extraLibraryPath=$HADOOP_HOME/*" \
--conf "spark.executor.extraClassPath=$(echo /your directory of jars/*.jar | tr ' ' ',')
val conf = new SparkConf().setAppName(appName).setJars(Seq(System.getProperty("user.dir") + "/target/scala-2.10/sparktest.jar"))
这应该可以解决绝大多数未发现的课程问题。另一种选择是将依赖项放在集群中所有工作节点上的默认类路径中。这样你就不必绕过一个大罐子。
类未找到问题的唯一其他主要问题源于使用的库的不同版本。例如,如果您在应用程序和spark服务器中不使用相同版本的公共库,则最终会出现类路径问题。当您针对一个版本的库(如Spark 1.1.0)进行编译,然后尝试针对具有不同或过时版本的集群(如Spark 0.9.2)运行时,可能会发生这种情况。确保您将库版本与正在加载到执行程序类路径上的任何内容匹配。一个常见的例子是编译Spark Cassandra Connector的alpha版本,然后尝试使用旧版本的类路径引用运行。