我的hadoop版本是1.0.3,当我使用多输入时,我收到了这个错误。
java.lang.ClassCastException: org.apache.hadoop.mapreduce.lib.input.TaggedInputSplit cannot be cast to org.apache.hadoop.mapreduce.lib.input.FileSplit
at org.myorg.textimage$ImageMapper.setup(textimage.java:80)
at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:142)
at org.apache.hadoop.mapreduce.lib.input.DelegatingMapper.run(DelegatingMapper.java:55)
at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:764)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:370)
at org.apache.hadoop.mapred.Child$4.run(Child.java:255)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:416)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1121)
at org.apache.hadoop.mapred.Child.main(Child.java:249)
我测试了单输入路径,没问题。只有当我使用
时MultipleInputs.addInputPath(job, TextInputpath, TextInputFormat.class,
TextMapper.class);
MultipleInputs.addInputPath(job, ImageInputpath,
WholeFileInputFormat.class, ImageMapper.class);
我用Google搜索并发现此链接https://issues.apache.org/jira/browse/MAPREDUCE-1178,其中0.21表示此错误。但是我使用1.0.3,这个bug又回来了。任何人都有同样的问题或任何人都可以告诉我如何解决它?感谢
这里是图像映射器的设置代码,第4行是发生错误的地方:
protected void setup(Context context) throws IOException,
InterruptedException {
InputSplit split = context.getInputSplit();
Path path = ((FileSplit) split).getPath();
try {
pa = new Text(path.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
答案 0 :(得分:32)
跟进我的评论,TaggedInputSplit
的Javadocs确认您可能错误地将输入拆分转换为FileSplit:
/**
* An {@link InputSplit} that tags another InputSplit with extra data for use
* by {@link DelegatingInputFormat}s and {@link DelegatingMapper}s.
*/
我的猜测是你的设置方法看起来像这样:
@Override
protected void setup(Context context) throws IOException,
InterruptedException {
FileSplit split = (FileSplit) context.getInputSplit();
}
不幸的是,TaggedInputSplit
无法公开显示,因此您无法轻松进行{{1}}样式检查,然后进行转换,然后调用instanceof
以获取实际的基础FileSplit。因此,您需要自己更新源代码并重新编译和部署,发布JIRA票证,要求在未来版本中修复它(如果它已经没有在2+中执行)或执行一些讨厌的令人讨厌的反射hackery来到底层的InputSplit
这是完全未经测试的:
TaggedInputSplit.getInputSplit()
反思Hackery解释:
如果TaggedInputSplit被声明为受保护范围,则@Override
protected void setup(Context context) throws IOException,
InterruptedException {
InputSplit split = context.getInputSplit();
Class<? extends InputSplit> splitClass = split.getClass();
FileSplit fileSplit = null;
if (splitClass.equals(FileSplit.class)) {
fileSplit = (FileSplit) split;
} else if (splitClass.getName().equals(
"org.apache.hadoop.mapreduce.lib.input.TaggedInputSplit")) {
// begin reflection hackery...
try {
Method getInputSplitMethod = splitClass
.getDeclaredMethod("getInputSplit");
getInputSplitMethod.setAccessible(true);
fileSplit = (FileSplit) getInputSplitMethod.invoke(split);
} catch (Exception e) {
// wrap and re-throw error
throw new IOException(e);
}
// end reflection hackery
}
}
包之外的类不可见,因此您无法在安装方法中引用该类。为了解决这个问题,我们执行了许多基于反射的操作:
检查类名,我们可以使用它的完全限定名称来测试TaggedInputSplit类型
org.apache.hadoop.mapreduce.lib.input
我们知道我们想调用splitClass.getName().equals("org.apache.hadoop.mapreduce.lib.input.TaggedInputSplit")
方法来恢复包装的输入分割,因此我们使用TaggedInputSplit.getInputSplit()
反射方法来获取对方法的引用:
Class.getMethod(..)
该类仍然不公开,因此我们使用setAccessible(..)方法来覆盖它,阻止安全管理器抛出异常
Method getInputSplitMethod = splitClass.getDeclaredMethod("getInputSplit");
最后,我们在对输入拆分的引用上调用方法,并将结果转换为FileSplit(乐观地希望它是这种类型的实例!):
getInputSplitMethod.setAccessible(true);
答案 1 :(得分:0)
我遇到了同样的问题,但实际问题是我在设置MultipleInputs后仍在设置InputFormat:
job.setInputFormatClass(SequenceFileInputFormat.class);
删除此行后,一切正常。