18

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

私はグーグルでこのリンク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();
        }
    }
4

2 に答える 2

32

私のコメントに続いてTaggedInputSplit、 Javadocs for は、入力分割を 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パッケージ外のクラスからは見えないため、setup メソッドでそのクラスを参照できません。これを回避するために、いくつかのリフレクション ベースの操作を実行します。

  1. クラス名を調べると、完全修飾名を使用して TaggedInputSplit 型をテストできます

    splitClass.getName().equals("org.apache.hadoop.mapreduce.lib.input.TaggedInputSplit")

  2. TaggedInputSplit.getInputSplit()ラップされた入力分割を回復するためにメソッドを呼び出したいことがわかっているので、Class.getMethod(..)リフレクション メソッドを使用してメソッドへの参照を取得します。

    Method getInputSplitMethod = splitClass.getDeclaredMethod("getInputSplit");

  3. クラスはまだ公開されていないため、setAccessible(..) メソッドを使用してこれをオーバーライドし、セキュリティ マネージャーが例外をスローしないようにします。

    getInputSplitMethod.setAccessible(true);

  4. 最後に、入力分割への参照でメソッドを呼び出し、結果を FileSplit にキャストします (このタイプのインスタンスであることが楽観的に期待できます!)。

    fileSplit = (FileSplit) getInputSplitMethod.invoke(split);

于 2012-06-21T01:30:23.240 に答える
0

これと同じ問題がありましたが、実際の問題は、MultipleInputs を設定した後も InputFormat を設定していたことです。

job.setInputFormatClass(SequenceFileInputFormat.class);

この行を削除すると、すべて正常に機能しました。

于 2013-12-06T16:02:45.827 に答える