Hadoop的ObjectWritable保存了一个能够在Hadoop RPC里面传输的对象和对象类型的说明信息。用于客户端与服务器间传输的Writable对象,也是对RPC传输对象的封装,由于RPC上交换的信息只能是JAVA的基础数据类型,String或者Writable类型,而ObjectWritable是对其子类的抽象封装,该类大体状况以下:java
ObjectWritable会往流里写入以下信息:数组
对象类名,对象本身的串行化结果服务器
其序列化和反序列化方法以下:oop
public void readFields(DataInput in) throws IOException { readObject(in, this, this.conf); } public void write(DataOutput out) throws IOException { writeObject(out, instance, declaredClass, conf); }
分别调用的是writeObject(out, instance, declaredClass, conf)和readObject(in, this, this.conf)方法:this
writeObject(out, instance, declaredClass, conf)方法:该方法逐一分析待xulie的数据类型而且实现序列化。spa
public static void writeObject(DataOutput out, Object instance, Class declaredClass, Configuration conf) throws IOException { //对象为空则抽象出内嵌数据类型NullInstance if (instance == null) { // null instance = new NullInstance(declaredClass, conf); declaredClass = Writable.class; } //先写入类名 UTF8.writeString(out, declaredClass.getName()); // always write declared /* * 封装的对象为数组类型,则逐个序列化(序列化为length+对象的序列化内容) * 采用了迭代 */ if (declaredClass.isArray()) { // array int length = Array.getLength(instance); out.writeInt(length); for (int i = 0; i < length; i++) { writeObject(out, Array.get(instance, i), declaredClass.getComponentType(), conf); } //为String类型直接写入 } else if (declaredClass == String.class) { // String UTF8.writeString(out, (String)instance); }//基本数据类型写入 else if (declaredClass.isPrimitive()) { // primitive type if (declaredClass == Boolean.TYPE) { // boolean out.writeBoolean(((Boolean)instance).booleanValue()); } else if (declaredClass == Character.TYPE) { // char out.writeChar(((Character)instance).charValue()); } else if (declaredClass == Byte.TYPE) { // byte out.writeByte(((Byte)instance).byteValue()); } else if (declaredClass == Short.TYPE) { // short out.writeShort(((Short)instance).shortValue()); } else if (declaredClass == Integer.TYPE) { // int out.writeInt(((Integer)instance).intValue()); } else if (declaredClass == Long.TYPE) { // long out.writeLong(((Long)instance).longValue()); } else if (declaredClass == Float.TYPE) { // float out.writeFloat(((Float)instance).floatValue()); } else if (declaredClass == Double.TYPE) { // double out.writeDouble(((Double)instance).doubleValue()); } else if (declaredClass == Void.TYPE) { // void } else { throw new IllegalArgumentException("Not a primitive: "+declaredClass); } //枚举类型写入 } else if (declaredClass.isEnum()) { // enum UTF8.writeString(out, ((Enum)instance).name()); //hadoop的Writable类型写入 } else if (Writable.class.isAssignableFrom(declaredClass)) { // Writable UTF8.writeString(out, instance.getClass().getName()); ((Writable)instance).write(out); } else { throw new IOException("Can't write: "+instance+" as "+declaredClass); } }
对于readObject(in, this, this.conf)方法:该方法用于反序列化,在ObjectWritable对象内部封装了一个基本数据类型的注册表.net
经过if语句条件实现基本数据类型的反序列化,而对于实现了Writbale接口的封装数据,则是经过Conf对象获取其类声明,其反序列化的code
实例化也是调用WritableFactories工程去实例化,最后在存储反序列化的值。对象
public static Object readObject(DataInput in, Configuration conf) throws IOException { return readObject(in, null, conf); } /** Read a {@link Writable}, {@link String}, primitive type, or an array of * the preceding. */ @SuppressWarnings("unchecked") public static Object readObject(DataInput in, ObjectWritable objectWritable, Configuration conf) throws IOException { //获取反序列化的名字 String className = UTF8.readString(in); //假设为基本数据类型 Class<?> declaredClass = PRIMITIVE_NAMES.get(className); /* * 判断是否为基本数据类型,不是则为空,则为Writable类型, * 对于Writable类型从Conf配置文件中读取类名, * 在这里只是获取类名,而并无反序列化对象 */ if (declaredClass == null) { try { declaredClass = conf.getClassByName(className); } catch (ClassNotFoundException e) { throw new RuntimeException("readObject can't find class " + className, e); } } //基本数据类型 Object instance; //为基本数据类型,逐一反序列化 if (declaredClass.isPrimitive()) { // primitive types if (declaredClass == Boolean.TYPE) { // boolean instance = Boolean.valueOf(in.readBoolean()); } else if (declaredClass == Character.TYPE) { // char instance = Character.valueOf(in.readChar()); } else if (declaredClass == Byte.TYPE) { // byte instance = Byte.valueOf(in.readByte()); } else if (declaredClass == Short.TYPE) { // short instance = Short.valueOf(in.readShort()); } else if (declaredClass == Integer.TYPE) { // int instance = Integer.valueOf(in.readInt()); } else if (declaredClass == Long.TYPE) { // long instance = Long.valueOf(in.readLong()); } else if (declaredClass == Float.TYPE) { // float instance = Float.valueOf(in.readFloat()); } else if (declaredClass == Double.TYPE) { // double instance = Double.valueOf(in.readDouble()); } else if (declaredClass == Void.TYPE) { // void instance = null; } else { throw new IllegalArgumentException("Not a primitive: "+declaredClass); } } else if (declaredClass.isArray()) { // array int length = in.readInt(); instance = Array.newInstance(declaredClass.getComponentType(), length); for (int i = 0; i < length; i++) { Array.set(instance, i, readObject(in, conf)); } } else if (declaredClass == String.class) { // String类型的反序列化 instance = UTF8.readString(in); } else if (declaredClass.isEnum()) { // enum的反序列化 instance = Enum.valueOf((Class<? extends Enum>) declaredClass, UTF8.readString(in)); } else { // Writable Class instanceClass = null; String str = ""; try { //剩下的从Conf对象中获取类型Class str = UTF8.readString(in); instanceClass = conf.getClassByName(str); } catch (ClassNotFoundException e) { throw new RuntimeException("readObject can't find class " + str, e); } /* * 带用了WritableFactories工厂去new instanceClass(实现了Writable接口)对象出来 * 在调用实现Writable对象自身的反序列化方法 */ Writable writable = WritableFactories.newInstance(instanceClass, conf); writable.readFields(in); instance = writable; if (instanceClass == NullInstance.class) { // null declaredClass = ((NullInstance)instance).declaredClass; instance = null; } } //最后存储反序列化后待封装的ObjectWritable对象 if (objectWritable != null) { // store values objectWritable.declaredClass = declaredClass; objectWritable.instance = instance; } return instance; }
对于Null类型的封装,在ObjectWritable内部封装了一个Nullinstance接口
private static class NullInstance extends Configured implements Writable { private Class<?> declaredClass; public NullInstance() { super(null); } public NullInstance(Class declaredClass, Configuration conf) { super(conf); this.declaredClass = declaredClass; }