hdfs에서 ReflectionUtils가 ObjectWritable 내부 클래스 NullIn을 실례화...

hadoop 버전: 1.0.3
문제 설명:
DataNode 부팅 코드를 연구할 때 Hadoop 도구 클래스인 Reflection Utils를 통해 NullInstance 실례를 반사하여 생성할 때 NullInstance 부모 클래스인 Configured의 구성원 변수 conf가 올바르게 부여되지 않았고, 올바르게 부여되지 않았기 때문에 다음 코드에서 빈 바늘 이상이 던져집니다.
문제 분석:
Hadoop은 ObjectWritable 객체의 반서열화 과정에서 비기본 유형에 대해 반사를 통해 대응하는 클래스 실례를 생성하고 이 과정에서 클래스가 인터페이스Configurable의 실현 클래스인지에 따라 구성원 변수 conf의 값을 부여한다.관련 코드는 다음과 같습니다.
ObjectWritable:
public static Object readObject(DataInput in, ObjectWritable objectWritable, Configuration conf)
    throws IOException {
      ... 
      Writable writable = WritableFactories.newInstance(instanceClass, conf);
      writable.readFields(in);
      instance = writable;

      ...
      
  }

WritableFactories:
public static Writable newInstance(Class<? extends Writable> c, Configuration conf) {
    WritableFactory factory = WritableFactories.getFactory(c);
    if (factory != null) {
      Writable result = factory.newInstance();
      if (result instanceof Configurable) {
        ((Configurable) result).setConf(conf);
      }
      return result;
    } else {
      return ReflectionUtils.newInstance(c, conf);
    }
  }

ReflectionUtils:
public static <T> T newInstance(Class<T> theClass, Configuration conf) {
		T result;
		try {
			Constructor<T> meth = (Constructor<T>) CONSTRUCTOR_CACHE
					.get(theClass);
			if (meth == null) {
				meth = theClass.getDeclaredConstructor(EMPTY_ARRAY);
				meth.setAccessible(true);
				CONSTRUCTOR_CACHE.put(theClass, meth);
			}
			result = meth.newInstance();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		setConf(result, conf);
		return result;
	}
public static void setConf(Object theObject, Configuration conf) {
 if (conf != null) {
      if (theObject instanceof Configurable) {
            ((Configurable) theObject).setConf(conf);
      }
      setJobConf(theObject, conf);
 }
}  

NullInstance의 클래스 정의로 돌아갑니다. 클래스Configured를 계승했기 때문에, 이것은 NullInstance가 실례화될 때 conf 대상을 초기화해야 한다는 것을 의미합니다.conf 객체가 제대로 초기화되지 않은 경우 빈 포인터 오류와 같이 프로그램 예외가 발생할 수 있습니다. conf가 비어 있으면 다음 코드를 실행할 때 포인터 예외가 발생합니다.
NullInstance:
public void readFields(DataInput in) throws IOException {
      String className = Text.readString(in);
      declaredClass = PRIMITIVE_NAMES.get(className);
      if (declaredClass == null) {
        try {
          //    getConf()    null
          declaredClass = getConf().getClassByName(className); 
        } catch (ClassNotFoundException e) {
          throw new RuntimeException(e.toString());
        }
      }
    }

문제 해결:
ReflectionUtils 메서드 setConf에 코드를 추가하려면 다음과 같이 하십시오.
if(Configured.class.isAssignableFrom(theObject.getClass())){
	((Configured)theObject).setConf(conf);
}

좋은 웹페이지 즐겨찾기