Ответ 1
Следуя моему комментарию, Javadocs для TaggedInputSplit
подтверждает, что вы, вероятно, ошибочно бросаете входной раскол в 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
не является общедоступным, поэтому вы не можете легко выполнить проверку стиля instanceof
, за которым следует бросок, а затем вызвать TaggedInputSplit.getInputSplit()
, чтобы получить фактический базовый FileSplit. Таким образом, либо вам нужно будет обновить исходный код самостоятельно, либо повторно собрать и развернуть, разместите билет JIRA, чтобы попросить его исправить в будущей версии (если он уже не был активирован в 2+) или выполнить некоторые неприятные неприятные размышления хакеры, чтобы попасть в базовый InputSplit
Это полностью не проверено:
@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
, и поэтому вы не можете ссылаться на этот класс в своем методе установки. Чтобы обойти это, мы выполняем ряд операций, основанных на отражении:
-
Проверяя имя класса, мы можем проверить тип TaggedInputSplit, используя его полное имя
splitClass.getName().equals("org.apache.hadoop.mapreduce.lib.input.TaggedInputSplit")
-
Мы знаем, что хотим вызвать метод
TaggedInputSplit.getInputSplit()
для восстановления разбитого входного разделения, поэтому мы используем метод отраженияClass.getMethod(..)
для получения ссылки на метод:Method getInputSplitMethod = splitClass.getDeclaredMethod("getInputSplit");
-
Класс по-прежнему не является общедоступным, поэтому мы используем метод setAccessible (..), чтобы переопределить это, остановив диспетчера безопасности от выброса исключения
getInputSplitMethod.setAccessible(true);
-
Наконец, мы вызываем метод по ссылке на входной split и передаем результат в FileSplit (оптимистично надеясь, что это экземпляр этого типа!):
fileSplit = (FileSplit) getInputSplitMethod.invoke(split);