2012-06-21 30 views
15

Phiên bản hadoop của tôi là 1.0.3, khi tôi sử dụng nhiều kết quả, tôi nhận được lỗi này.Nhiều đầu vào hadoop không thành công với 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) 

Tôi đã thử nghiệm đường dẫn nhập đơn, không thành vấn đề. Chỉ khi tôi sử dụng

MultipleInputs.addInputPath(job, TextInputpath, TextInputFormat.class, 
      TextMapper.class); 
    MultipleInputs.addInputPath(job, ImageInputpath, 
      WholeFileInputFormat.class, ImageMapper.class); 

Tôi đã tìm kiếm và tìm thấy liên kết này https://issues.apache.org/jira/browse/MAPREDUCE-1178 cho biết 0,21 đã có lỗi này. Nhưng tôi đang sử dụng 1.0.3, lỗi này có quay lại không. Bất cứ ai có cùng một vấn đề hoặc bất cứ ai có thể cho tôi biết làm thế nào để sửa chữa nó? Cảm ơn

đây là mã thiết lập các mapper hình ảnh, dòng thứ 4 là nơi mà các lỗi xảy ra:

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

Bạn có thể đăng mã cho lớp 'ImageMapper' của mình không - có vẻ như bạn đang cố gắng tách phần nhập liệu thành một FileInputSplit trong phương thức thiết lập của bạn. –

+0

Tôi có vấn đề tương tự .. Có giải pháp nào tồn tại không? – sunitha

Trả lời

29

Theo dõi trên nhận xét của tôi, Javadocs cho TaggedInputSplit xác nhận rằng bạn có thể là sai đúc chia đầu vào một FileSplit:

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

tôi đoán là phương pháp thiết lập của bạn trông giống như sau:

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

Thật không may TaggedInputSplit không hiển thị công khai, vì vậy bạn không thể dễ dàng thực hiện kiểm tra kiểu instanceof, tiếp theo là dàn diễn viên và sau đó gọi tới TaggedInputSplit.getInputSplit() để nhận FileSplit cơ bản thực tế. Vì vậy, bạn cần tự cập nhật nguồn và biên dịch lại triển khai &, đăng một vé JIRA để yêu cầu điều này được khắc phục trong phiên bản sau (nếu nó chưa được thực hiện trong 2+) hoặc thực hiện một số khó chịu khó chịu phản ánh hackery để đến InputSplit tiềm ẩn

này là hoàn toàn chưa được kiểm tra:

@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 
    } 
} 

Reflection hackery giải thích:

với TaggedInputSplit là phạm vi bảo vệ công bố, nó không nhìn thấy được cho các lớp bên ngoài gói org.apache.hadoop.mapreduce.lib.input và do đó bạn không thể tham chiếu lớp đó trong phương pháp thiết lập của mình. Để làm được việc này, chúng tôi thực hiện một số hoạt động dựa trên phản ánh:

  1. Kiểm tra tên lớp, chúng ta có thể kiểm tra cho các loại TaggedInputSplit sử dụng nó là tên đầy đủ

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

  2. Chúng tôi biết chúng tôi muốn gọi phương thức TaggedInputSplit.getInputSplit() để khôi phục phần tách đầu vào được bao bọc, vì vậy, chúng tôi sử dụng phương pháp phản chiếu Class.getMethod(..) để có được tham chiếu đến phương pháp:

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

  3. Lớp học vẫn không hiển thị công khai nên chúng tôi sử dụng setAccessible (..) Phương pháp để ghi đè này, dừng quản lý bảo mật từ ném một ngoại lệ

    getInputSplitMethod.setAccessible(true);

  4. Cuối cùng chúng ta gọi phương pháp này trên tham chiếu đến sự phân chia đầu vào và đúc kết quả vào một FileSplit (một cách lạc quan hy vọng một ví dụ của loại này):

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

+1

Nó chính xác giống như những gì bạn đoán. Tôi đã thử mã của bạn và nó hiện đang hoạt động. Bạn thật chuyên nghiệp! –

+0

Tôi đã đọc lại mã nhưng tôi vẫn không chắc chắn cách thức hoạt động của mã. Bạn có thể đưa ra một lời giải thích ngắn gọn về hackery phản chiếu không? Cảm ơn. –

+0

Xem phần được thêm vào ở cuối –

0

tôi có vấn đề này như nhau, nhưng vấn đề thực tế là tôi vẫn đang thiết lập các InputFormat sau khi thiết lập the MultipleInputs:

job.setInputFormatClass(SequenceFileInputFormat.class); 

Khi tôi xóa dòng này mọi thứ hoạt động tốt.

Các vấn đề liên quan