2012-06-21 4 views
15

내 hadoop 버전이 1.0.3이고 multipleinputs를 사용할 때이 오류가 발생합니다.hadoop MultipleInputs가 ClassCastException과 함께 실패합니다.

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

를 사용하는 경우에만 검색 좀하고 0.21이이 버그가 열악하다고 말했습니다 링크 https://issues.apache.org/jira/browse/MAPREDUCE-1178를 발견했다. 하지만 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(); 
     } 
    } 
+0

'ImageMapper'클래스의 코드를 게시 할 수 있습니까? 설정 방법에서 입력 분할을 FileInputSplit으로 캐스팅하려는 것처럼 보입니다. –

+0

비슷한 문제점이 있습니다. 해결책이 있습니까? – sunitha

답변

29

를 내 댓글에까지 이어 TaggedInputSplit에 대한 Javadoc과는 잘못에 대한 입력 분할을 캐스팅 아마 것을 확인 FileSplit :

@Override 
protected void setup(Context context) throws IOException, 
     InterruptedException { 
    FileSplit split = (FileSplit) context.getInputSplit(); 
} 
012 :

/** 
* An {@link InputSplit} that tags another InputSplit with extra data for use 
* by {@link DelegatingInputFormat}s and {@link DelegatingMapper}s. 
*/ 

내 생각 엔 당신의 설정 방법은 다음과 같이 보입니다

불행히도 TaggedInputSplit은 공개되어 있지 않으므로 instanceof 스타일 확인을 한 다음 캐스팅을 쉽게 수행하고 TaggedInputSplit.getInputSplit()을 호출하여 실제 기본 FileSplit을 가져올 수 있습니다. 따라서 소스를 직접 업데이트하고 & 배포를 다시 컴파일하거나, JIRA 티켓을 게시하여 향후 버전에서 수정되도록 요청하거나 (이미 2 이상으로 실행되지 않은 경우) 또는 불쾌한 을 수행해야합니다. 해커 설명

@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 것을 선언 보호 범위와

, 그것은 보이지 않는 반사 해커는 기본 InputSplit

이 완전히 안된에 도착합니다 org.apache.hadoop.mapreduce.lib.input 패키지 외부의 클래스에 적용되므로 설정 메소드에서 해당 클래스를 참조 할 수 없습니다. 이 문제를 얻으려면, 우리는 반사 기반 작업의 번호를 수행 클래스 이름을 검사

  1. 을, 우리는 완전한 이름

    우리는 알고 splitClass.getName().equals("org.apache.hadoop.mapreduce.lib.input.TaggedInputSplit")

  2. 의 사용 유형 TaggedInputSplit을 테스트 할 수 있습니다 우리는 TaggedInputSplit.getInputSplit() 메서드를 호출하여 래핑 된 입력 분할을 복구하기 때문에 Class.getMethod(..) 반사 메서드를 사용하여 메서드에 대한 참조를 얻습니다.

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

  3. 클래스는 여전히 공개되지 않으므로 setAccessible (..낙관적의 자사의 인스턴스를 희망) 방법은

    getInputSplitMethod.setAccessible(true);

  4. 마지막으로 우리는 입력 분할에 대한 참조에 메소드를 호출 예외를 throw에서 보안 관리자를 중지,이를 무시하고 FileSplit (에 결과를 캐스팅 이러한 유형의) :!

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

+1

그것은 당신이 짐작했던 것과 정확히 같습니다. 나는 당신의 코드를 시도했고 그것은 지금 일하고있다. 당신은 프로입니다! –

+0

코드를 다시 읽었지만 어떻게 작동하는지 아직 잘 모릅니다. 반성 해커리에 대해 간단한 설명을 해줄 수 있습니까? 감사. –

+0

끝에있는 추가 섹션을 참조하십시오. –

0

나는이 같은 문제를했지만, 실제 문제는 여전히 설정 한 후 InputFormat을 설정 한 것이 었습니다 MultipleInputs :

job.setInputFormatClass(SequenceFileInputFormat.class); 

이 줄을 제거하면 모든 것이 잘 동작합니다.

관련 문제