Подтвердить что ты не робот

Hasoop MultipleInputs терпит неудачу с ClassCastException

Моя версия hadoop 1.0.3, когда я использую multipleinputs, я получил эту ошибку.

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); 

Я googled и нашел эту ссылку https://issues.apache.org/jira/browse/MAPREDUCE-1178, которая сказала, что у 0.21 была эта ошибка. Но я использую 1.0.3, эта ошибка возвращается снова. У кого-то такая же проблема, или кто-нибудь может сказать мне, как ее исправить? Благодаря

вот код установки устройства отображения изображений, 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();
        }
    }
4b9b3361

Ответ 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);

Ответ 2

У меня была такая же проблема, но проблема в том, что я все еще устанавливал InputFormat после настройки MultipleInputs:

job.setInputFormatClass(SequenceFileInputFormat.class);

Как только я удалил эту строку, все работало нормально.