序列化

作者: 南园故剑00 | 来源:发表于2020-06-12 11:24 被阅读0次

    1. 序列化的意义

    1. 含义
    • 序列化是把对象的状态信息转化为可存储或者传输的形式的过程,也就是把对象转化为字节序列的过程称为对象的序列化。

    • 反序列化是把字节序列恢复为对象的过程称为对象的反序列化

    序列化就是把实体对象状态按照一定的格式写入到有序字节流,反序列化就是从有序字节流重建对象,恢复对象状态

    1. 意义

    (1)永久性保存对象,保存对象的字节序列到本地文件或者数据库中;

    (2)通过序列化以字节流的形式使对象在网络中进行传递和接收;

    (3)通过序列化在进程间传递对象;

    1. 序列化算法一般会按步骤做如下事情

    (1)将对象实例相关的类元数据输出。

    (2)递归地输出类的超类描述直到不再有超类。

    (3)类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。

    (4)从上至下递归输出实例的数据

    2. 优劣指标:

    1. 序列化后的数据大小

    2. 序列化操作本省的速度以及系统资源开销:CPU、内存

    3. JDK的序列化:

    3.1 一个类只要实现了 java.io.Serializable 接口,那就可以被序列化

    /**
     * @description:
     * @date : 2020/1/7 22:56
     * @author: zwz
     */
    public interface ISerializer {
    
        <T> byte[] serializer(T obj);
    
        <T> T deSerializer(byte[] data, Class<T> clazz);
    }
    

    3.2 通过输出流 java.io.ObjectOutputStream 和对象输入流 java.io.ObjectInputStream 来实现

    package com.gp.lock.serizlizer;
    
    import java.io.*;
    
    /**
     * @description: 基于JDK实现序列化
     * @date : 2020/1/7 22:58
     * @author: zwz
     */
    public class JavaSerializer implements ISerializer {
    
        /**
         * 序列化
         * 使用输出流
         * @param obj
         * @param <T>
         * @return
         */
        public <T> byte[] serializer(T obj) {
            ByteArrayOutputStream byteArrayOutputStream = null;
            ObjectOutputStream objectOutputStream = null;
            try {
                byteArrayOutputStream = new ByteArrayOutputStream();
                objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
                objectOutputStream.writeObject(obj);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (objectOutputStream != null) {
                        objectOutputStream.close();
                    }
                    if (byteArrayOutputStream != null) {
                        byteArrayOutputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return byteArrayOutputStream.toByteArray();
        }
    
        /**
         * 反序列化
         * 使用输入流
         * @param data
         * @param clazz
         * @param <T>
         * @return
         */
        public <T> T deSerializer(byte[] data, Class<T> clazz) {
            ByteArrayInputStream byteArrayInputStream = null;
            ObjectInputStream objectInputStream = null;
            Object result = null;
    
            try {
                byteArrayInputStream = new ByteArrayInputStream(data);
                objectInputStream = new ObjectInputStream(byteArrayInputStream);
                result = objectInputStream.readObject();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (byteArrayInputStream != null) {
                        byteArrayInputStream.close();
                    }
                    if (objectInputStream != null) {
                        objectInputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
            return (T) result;
        }
    }
    

    3.3 实例

    package com.gp.lock.serizlizer;
    
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.util.Arrays;
    
    /**
     * @description:
     * @date : 2020/1/7 23:11
     * @author: zwz
     */
    public class User /*extends SuperClass*/ implements Serializable {
    
        private static final long serialVersionUID = 6322539910270175988L;
    
        public static int num = 5;
    
        private String name;
    
        private int age;
    
        private transient String hobby;
    
        public String getHobby() {
            return hobby;
        }
    
        public void setHobby(String hobby) {
            this.hobby = hobby;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public static int getNum() {
            return num;
        }
    
        public static void setNum(int num) {
            User.num = num;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", hobby='" + hobby + '\'' +
                    '}';
        }
    
        private void writeObject(ObjectOutputStream outputStream) throws IOException {
            outputStream.defaultWriteObject();
            outputStream.writeObject(hobby);
        }
    
        private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
            inputStream.defaultReadObject();
            hobby = (String) inputStream.readObject();
        }
    
        public static void main(String[] args) {
            ISerializer serializer = new JavaSerializer();
            User user = new User();
            user.setAge(18);
            user.setName("mic");
    
            byte[] bytes = serializer.serializer(user);
            System.out.println(Arrays.toString(bytes));
    
            User deSerializer = serializer.deSerializer(bytes, User.class);
            System.out.println(deSerializer);
        }
    }
    

    4. 高阶认识

    4.1 serialVersionUID 的作用

    • Java的序列化机制是通过判断类的 serialVersionUID 来验证版本一致性的。

    • 在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体的serialVersionUID进行比较,如果相同就认为时一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是 InvalidCastException。

    • 如果没有为指定的 class 配置 serialVersionUID,那么 java 编译器会自动给这个 class 进行一个摘要算法,类似于指纹算法,只要这个文件有任何改动,得到的 UID 就会截然不同的,可以保证在这么多类中,这个编号是唯一的

    4.2 静态变量序列化

    序列化保存的是对象的状态,静态变量属于类的状态,因此序列化并不保存静态变量。

    4.3 父类的序列化

    1. 当一个父类没有实现序列化时,子类继承该父类并且实现了序列化。在反序列化该子类后,是没办法获取到父类的属性的。

    2. 当一个父类实现序列化,子类自动实现序列化,不需要再显示实现Serializable 接口

    3. 当一个对象的实例变量引用了其他对象,序列化该对象时也会把引用对象进行序列化,但是前提是该引用对象必须实现序列化接口

    4.4 Transient

    • Transient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中

    • 在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null

    5. 序列化实现深拷贝

    1. 浅克隆:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象

    2. 深克隆:

    • 被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的值。

    • 那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的哪些被引用的对象。

    • 深拷贝把要复制的对象所引用的对象都复制了一遍。

    package com.zwz.serializer;
    
    import java.io.*;
    
    /**
     * @description: 实现深克隆效果
     * 把对象序列化输出到一个流中,然后对象序列化流中读取出来,这个对象就不是原来的对象了。
     * @date : 2020/1/8 15:23
     * @author: zwz
     */
    public class Person implements Cloneable, Serializable {
    
        private static final long serialVersionUID = 5532843697249498959L;
    
        private String name;
    
        private Email email;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Email getEmail() {
            return email;
        }
    
        public void setEmail(Email email) {
            this.email = email;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", email=" + email.getContent() +
                    '}';
        }
    
        @Override
        protected Person clone() throws CloneNotSupportedException {
            return (Person) super.clone();
        }
    
        public Person deepClone() throws IOException, ClassNotFoundException {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(this);
    
            byte[] data = byteArrayOutputStream.toByteArray();
    
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
            ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
            Object object = objectInputStream.readObject();
            return (Person) object;
        }
    
        public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
            Email email = new Email();
            email.setContent("8:00");
    
            Person person = new Person();
            person.setName("mic");
            person.setEmail(email);
    
            Person person1 = person.deepClone();
            person1.setName("mak");
            person1.getEmail().setContent("9:00");
    
            System.out.println(person.getName() + "->" + person.getEmail().getContent());
            System.out.println(person1.getName() + "->" + person1.getEmail().getContent());
    
            System.out.println("-------------");
    
            Person person2 = person.clone();
            person2.setName("mac");
            person2.getEmail().setContent("10:00");
    
            System.out.println(person.getName() + "->" + person.getEmail().getContent());
            System.out.println(person1.getName() + "->" + person1.getEmail().getContent());
            System.out.println(person2.getName() + "->" + person2.getEmail().getContent());
        }
    
        /**
         * @description:
         * @date : 2020/1/8 15:21
         * @author: zwz
         */
        public static class Email implements Serializable {
    
            private static final long serialVersionUID = -2800552551799395733L;
    
            public Email(String content) {
                this.content = content;
            }
    
            private String content;
    
            public Email() {
    
            }
    
            public String getContent() {
                return content;
            }
    
            public void setContent(String content) {
                this.content = content;
            }
        }
    }
    

    6. 常见的序列化技术

    6.1 使用 JAVA 进行序列化有他的优点,也有他的缺点

    • 优点:JAVA 语言本身提供,使用比较方便和简单

    • 缺点:不支持跨语言处理、 性能相对不是很好,序列化以后产生的数据相对较大

    6.2 XML 序列化框架

    • XML 序列化的好处在于可读性好,方便阅读和调试。

    • 但是序列化以后的字节码文件比较大,而且效率不高。

    • 适用于对性能不高,而且 QPS 较低的企业级内部系统之间的数据交换的场景。

    • 同时 XML 又具有语言无关性,所以还可以用于异构系统之间的数据交换和协议。

    • Webservice采用 XML 格式对数据进行序列化的

    package com.gp.lock.serizlizer;
    
    import com.thoughtworks.xstream.XStream;
    import com.thoughtworks.xstream.io.xml.DomDriver;
    
    /**
     * @description:
     * @date : 2020/1/8 15:54
     * @author: zwz
     */
    public class XmlSerializer implements ISerializer {
    
        XStream xStream = new XStream(new DomDriver());
    
        public <T> byte[] serializer(T obj) {
            return xStream.toXML(obj).getBytes();
        }
    
        public <T> T deSerializer(byte[] data, Class<T> clazz) {
            return (T) xStream.fromXML(new String(data));
        }
    }
    

    6.3 JSON 序列化

    • JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,相对于 XML 来说,JSON 的字节流更小,而且可读性也非常好。

    • 现在 JSON数据格式在企业运用是最普遍的。JSON 序列化常用的开源工具有很多

      1. Jackson (https://github.com/FasterXML/jackson
      2. 阿里开源的 FastJson (https://github.com/alibaba/fastjon
      3. Google 的 GSON (https://github.com/google/gson)
    • 这几种 json 序列化工具中,Jackson 与 fastjson 要比 GSON 的性能要好,但是 Jackson、GSON 的稳定性要比 Fastjson 好。

    • 而 fastjson 的优势在于提供的 api 非常容易使用

    package com.gp.lock.serizlizer;
    
    import com.alibaba.fastjson.JSON;
    
    /**
     * @description:
     * @date : 2020/1/8 16:12
     * @author: zwz
     */
    public class FastJsonSerializer implements ISerializer {
    
        public <T> byte[] serializer(T obj) {
            return JSON.toJSONString(obj).getBytes();
        }
    
        public <T> T deSerializer(byte[] data, Class<T> clazz) {
            return JSON.parseObject(new String(data), clazz);
        }
    }
    

    6.4 Hessian 序列化框架

    • Hessian 是一个支持跨语言传输的二进制序列化协议,相对于 Java 默认的序列化机制来说,Hessian 具有更好的性能和易用性,而且支持多种不同的语言

    • Dubbo 采用的就是 Hessian 序列化来实现,只不过 Dubbo 对Hessian 进行了重构,性能更高

    7. Protobuf(Protocol Buffer) 序列化框架

    7.1 简介

    • Protobuf 是 Google 的一种数据交换格式,它独立于语言、独立于平台。

    • Google 提供了多种语言来实现,比如 Java、C、Go、Python,每一种实现都包含了相应语言的编译器和库文件。

    • Protobuf 使用比较广泛,主要是空间开销小和性能比较好,非常适合用于公司内部对性能要求高的 RPC 调用。

    • 由于解析性能比较高,序列化以后数据量相对较少,所以也可以应用在对象的持久化场景中

    • 但是要使用 Protobuf 会相对来说麻烦些,因为他有自己的语法,有自己的编译器

    7.2 使用实例

    1. 到官网下载protobuf的相应版本,我这里下载的是windows下的3.1.0版protoc-3.1.0-win32.zip

    2. 将下载好的zip解压,能看到bin目录下有一个protoc.exe的文件,等下需要用它来编译文件,我们直接在bin目录下创建一个简单的person.proto的描述文件

    syntax = "proto3";
    
    option java_package = "com.gp.lock.serizlizer.protobuf";
    option java_outer_classname = "PersonFactory";
    
    message Person{
    
         int32 id = 1;
         string name = 2;
         int32 age = 3;
         Addr addr = 4;
       
    }
    
    message Addr{
         
         string contry = 1;
         string city = 2;
    
    }
    
    1. 使用protoc编译上述.proto文件,生成Java类,使用如下命令完成该操作:protoc --java_out=./ ./person.proto

    2. 将PersonFactory.java文件引入到我们的项目中,并引入对应版本的protobuf的依赖包

    // Generated by the protocol buffer compiler.  DO NOT EDIT!
    // source: person.proto
    
    package com.gp.lock.serizlizer.protobuf;
    
    public final class PersonFactory {
        private PersonFactory() {
        }
    
        public static void registerAllExtensions(
                com.google.protobuf.ExtensionRegistryLite registry) {
        }
    
        public static void registerAllExtensions(
                com.google.protobuf.ExtensionRegistry registry) {
            registerAllExtensions(
                    (com.google.protobuf.ExtensionRegistryLite) registry);
        }
    
        public interface PersonOrBuilder extends
                // @@protoc_insertion_point(interface_extends:Person)
                com.google.protobuf.MessageOrBuilder {
    
            /**
             * <code>optional int32 id = 1;</code>
             */
            int getId();
    
            /**
             * <code>optional string name = 2;</code>
             */
            String getName();
    
            /**
             * <code>optional string name = 2;</code>
             */
            com.google.protobuf.ByteString
            getNameBytes();
    
            /**
             * <code>optional int32 age = 3;</code>
             */
            int getAge();
    
            /**
             * <code>optional .Addr addr = 4;</code>
             */
            boolean hasAddr();
    
            /**
             * <code>optional .Addr addr = 4;</code>
             */
            Addr getAddr();
    
            /**
             * <code>optional .Addr addr = 4;</code>
             */
            AddrOrBuilder getAddrOrBuilder();
        }
    
        /**
         * Protobuf type {@code Person}
         */
        public static final class Person extends
                com.google.protobuf.GeneratedMessageV3 implements
                // @@protoc_insertion_point(message_implements:Person)
                PersonOrBuilder {
            // Use Person.newBuilder() to construct.
            private Person(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
                super(builder);
            }
    
            private Person() {
                id_ = 0;
                name_ = "";
                age_ = 0;
            }
    
            @Override
            public final com.google.protobuf.UnknownFieldSet
            getUnknownFields() {
                return com.google.protobuf.UnknownFieldSet.getDefaultInstance();
            }
    
            private Person(
                    com.google.protobuf.CodedInputStream input,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws com.google.protobuf.InvalidProtocolBufferException {
                this();
                int mutable_bitField0_ = 0;
                try {
                    boolean done = false;
                    while (!done) {
                        int tag = input.readTag();
                        switch (tag) {
                            case 0:
                                done = true;
                                break;
                            default: {
                                if (!input.skipField(tag)) {
                                    done = true;
                                }
                                break;
                            }
                            case 8: {
    
                                id_ = input.readInt32();
                                break;
                            }
                            case 18: {
                                String s = input.readStringRequireUtf8();
    
                                name_ = s;
                                break;
                            }
                            case 24: {
    
                                age_ = input.readInt32();
                                break;
                            }
                            case 34: {
                                Addr.Builder subBuilder = null;
                                if (addr_ != null) {
                                    subBuilder = addr_.toBuilder();
                                }
                                addr_ = input.readMessage(Addr.parser(), extensionRegistry);
                                if (subBuilder != null) {
                                    subBuilder.mergeFrom(addr_);
                                    addr_ = subBuilder.buildPartial();
                                }
    
                                break;
                            }
                        }
                    }
                } catch (com.google.protobuf.InvalidProtocolBufferException e) {
                    throw e.setUnfinishedMessage(this);
                } catch (java.io.IOException e) {
                    throw new com.google.protobuf.InvalidProtocolBufferException(
                            e).setUnfinishedMessage(this);
                } finally {
                    makeExtensionsImmutable();
                }
            }
    
            public static final com.google.protobuf.Descriptors.Descriptor
            getDescriptor() {
                return PersonFactory.internal_static_Person_descriptor;
            }
    
            protected FieldAccessorTable
            internalGetFieldAccessorTable() {
                return PersonFactory.internal_static_Person_fieldAccessorTable
                        .ensureFieldAccessorsInitialized(
                                Person.class, Builder.class);
            }
    
            public static final int ID_FIELD_NUMBER = 1;
            private int id_;
    
            /**
             * <code>optional int32 id = 1;</code>
             */
            public int getId() {
                return id_;
            }
    
            public static final int NAME_FIELD_NUMBER = 2;
            private volatile Object name_;
    
            /**
             * <code>optional string name = 2;</code>
             */
            public String getName() {
                Object ref = name_;
                if (ref instanceof String) {
                    return (String) ref;
                } else {
                    com.google.protobuf.ByteString bs =
                            (com.google.protobuf.ByteString) ref;
                    String s = bs.toStringUtf8();
                    name_ = s;
                    return s;
                }
            }
    
            /**
             * <code>optional string name = 2;</code>
             */
            public com.google.protobuf.ByteString
            getNameBytes() {
                Object ref = name_;
                if (ref instanceof String) {
                    com.google.protobuf.ByteString b =
                            com.google.protobuf.ByteString.copyFromUtf8(
                                    (String) ref);
                    name_ = b;
                    return b;
                } else {
                    return (com.google.protobuf.ByteString) ref;
                }
            }
    
            public static final int AGE_FIELD_NUMBER = 3;
            private int age_;
    
            /**
             * <code>optional int32 age = 3;</code>
             */
            public int getAge() {
                return age_;
            }
    
            public static final int ADDR_FIELD_NUMBER = 4;
            private Addr addr_;
    
            /**
             * <code>optional .Addr addr = 4;</code>
             */
            public boolean hasAddr() {
                return addr_ != null;
            }
    
            /**
             * <code>optional .Addr addr = 4;</code>
             */
            public Addr getAddr() {
                return addr_ == null ? Addr.getDefaultInstance() : addr_;
            }
    
            /**
             * <code>optional .Addr addr = 4;</code>
             */
            public AddrOrBuilder getAddrOrBuilder() {
                return getAddr();
            }
    
            private byte memoizedIsInitialized = -1;
    
            public final boolean isInitialized() {
                byte isInitialized = memoizedIsInitialized;
                if (isInitialized == 1) return true;
                if (isInitialized == 0) return false;
    
                memoizedIsInitialized = 1;
                return true;
            }
    
            public void writeTo(com.google.protobuf.CodedOutputStream output)
                    throws java.io.IOException {
                if (id_ != 0) {
                    output.writeInt32(1, id_);
                }
                if (!getNameBytes().isEmpty()) {
                    com.google.protobuf.GeneratedMessageV3.writeString(output, 2, name_);
                }
                if (age_ != 0) {
                    output.writeInt32(3, age_);
                }
                if (addr_ != null) {
                    output.writeMessage(4, getAddr());
                }
            }
    
            public int getSerializedSize() {
                int size = memoizedSize;
                if (size != -1) return size;
    
                size = 0;
                if (id_ != 0) {
                    size += com.google.protobuf.CodedOutputStream
                            .computeInt32Size(1, id_);
                }
                if (!getNameBytes().isEmpty()) {
                    size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, name_);
                }
                if (age_ != 0) {
                    size += com.google.protobuf.CodedOutputStream
                            .computeInt32Size(3, age_);
                }
                if (addr_ != null) {
                    size += com.google.protobuf.CodedOutputStream
                            .computeMessageSize(4, getAddr());
                }
                memoizedSize = size;
                return size;
            }
    
            private static final long serialVersionUID = 0L;
    
            @Override
            public boolean equals(final Object obj) {
                if (obj == this) {
                    return true;
                }
                if (!(obj instanceof Person)) {
                    return super.equals(obj);
                }
                Person other = (Person) obj;
    
                boolean result = true;
                result = result && (getId()
                        == other.getId());
                result = result && getName()
                        .equals(other.getName());
                result = result && (getAge()
                        == other.getAge());
                result = result && (hasAddr() == other.hasAddr());
                if (hasAddr()) {
                    result = result && getAddr()
                            .equals(other.getAddr());
                }
                return result;
            }
    
            @Override
            public int hashCode() {
                if (memoizedHashCode != 0) {
                    return memoizedHashCode;
                }
                int hash = 41;
                hash = (19 * hash) + getDescriptorForType().hashCode();
                hash = (37 * hash) + ID_FIELD_NUMBER;
                hash = (53 * hash) + getId();
                hash = (37 * hash) + NAME_FIELD_NUMBER;
                hash = (53 * hash) + getName().hashCode();
                hash = (37 * hash) + AGE_FIELD_NUMBER;
                hash = (53 * hash) + getAge();
                if (hasAddr()) {
                    hash = (37 * hash) + ADDR_FIELD_NUMBER;
                    hash = (53 * hash) + getAddr().hashCode();
                }
                hash = (29 * hash) + unknownFields.hashCode();
                memoizedHashCode = hash;
                return hash;
            }
    
            public static Person parseFrom(
                    com.google.protobuf.ByteString data)
                    throws com.google.protobuf.InvalidProtocolBufferException {
                return PARSER.parseFrom(data);
            }
    
            public static Person parseFrom(
                    com.google.protobuf.ByteString data,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws com.google.protobuf.InvalidProtocolBufferException {
                return PARSER.parseFrom(data, extensionRegistry);
            }
    
            public static Person parseFrom(byte[] data)
                    throws com.google.protobuf.InvalidProtocolBufferException {
                return PARSER.parseFrom(data);
            }
    
            public static Person parseFrom(
                    byte[] data,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws com.google.protobuf.InvalidProtocolBufferException {
                return PARSER.parseFrom(data, extensionRegistry);
            }
    
            public static Person parseFrom(java.io.InputStream input)
                    throws java.io.IOException {
                return com.google.protobuf.GeneratedMessageV3
                        .parseWithIOException(PARSER, input);
            }
    
            public static Person parseFrom(
                    java.io.InputStream input,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws java.io.IOException {
                return com.google.protobuf.GeneratedMessageV3
                        .parseWithIOException(PARSER, input, extensionRegistry);
            }
    
            public static Person parseDelimitedFrom(java.io.InputStream input)
                    throws java.io.IOException {
                return com.google.protobuf.GeneratedMessageV3
                        .parseDelimitedWithIOException(PARSER, input);
            }
    
            public static Person parseDelimitedFrom(
                    java.io.InputStream input,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws java.io.IOException {
                return com.google.protobuf.GeneratedMessageV3
                        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
            }
    
            public static Person parseFrom(
                    com.google.protobuf.CodedInputStream input)
                    throws java.io.IOException {
                return com.google.protobuf.GeneratedMessageV3
                        .parseWithIOException(PARSER, input);
            }
    
            public static Person parseFrom(
                    com.google.protobuf.CodedInputStream input,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws java.io.IOException {
                return com.google.protobuf.GeneratedMessageV3
                        .parseWithIOException(PARSER, input, extensionRegistry);
            }
    
            public Builder newBuilderForType() {
                return newBuilder();
            }
    
            public static Builder newBuilder() {
                return DEFAULT_INSTANCE.toBuilder();
            }
    
            public static Builder newBuilder(Person prototype) {
                return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
            }
    
            public Builder toBuilder() {
                return this == DEFAULT_INSTANCE
                        ? new Builder() : new Builder().mergeFrom(this);
            }
    
            @Override
            protected Builder newBuilderForType(
                    BuilderParent parent) {
                Builder builder = new Builder(parent);
                return builder;
            }
    
            /**
             * Protobuf type {@code Person}
             */
            public static final class Builder extends
                    com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
                    // @@protoc_insertion_point(builder_implements:Person)
                    PersonOrBuilder {
                public static final com.google.protobuf.Descriptors.Descriptor
                getDescriptor() {
                    return PersonFactory.internal_static_Person_descriptor;
                }
    
                protected FieldAccessorTable
                internalGetFieldAccessorTable() {
                    return PersonFactory.internal_static_Person_fieldAccessorTable
                            .ensureFieldAccessorsInitialized(
                                    Person.class, Builder.class);
                }
    
                // Construct using com.gp.lock.serizlizer.protobuf.PersonFactory.Person.newBuilder()
                private Builder() {
                    maybeForceBuilderInitialization();
                }
    
                private Builder(
                        BuilderParent parent) {
                    super(parent);
                    maybeForceBuilderInitialization();
                }
    
                private void maybeForceBuilderInitialization() {
                    if (com.google.protobuf.GeneratedMessageV3
                            .alwaysUseFieldBuilders) {
                    }
                }
    
                public Builder clear() {
                    super.clear();
                    id_ = 0;
    
                    name_ = "";
    
                    age_ = 0;
    
                    if (addrBuilder_ == null) {
                        addr_ = null;
                    } else {
                        addr_ = null;
                        addrBuilder_ = null;
                    }
                    return this;
                }
    
                public com.google.protobuf.Descriptors.Descriptor
                getDescriptorForType() {
                    return PersonFactory.internal_static_Person_descriptor;
                }
    
                public Person getDefaultInstanceForType() {
                    return Person.getDefaultInstance();
                }
    
                public Person build() {
                    Person result = buildPartial();
                    if (!result.isInitialized()) {
                        throw newUninitializedMessageException(result);
                    }
                    return result;
                }
    
                public Person buildPartial() {
                    Person result = new Person(this);
                    result.id_ = id_;
                    result.name_ = name_;
                    result.age_ = age_;
                    if (addrBuilder_ == null) {
                        result.addr_ = addr_;
                    } else {
                        result.addr_ = addrBuilder_.build();
                    }
                    onBuilt();
                    return result;
                }
    
                public Builder clone() {
                    return (Builder) super.clone();
                }
    
                public Builder setField(
                        com.google.protobuf.Descriptors.FieldDescriptor field,
                        Object value) {
                    return (Builder) super.setField(field, value);
                }
    
                public Builder clearField(
                        com.google.protobuf.Descriptors.FieldDescriptor field) {
                    return (Builder) super.clearField(field);
                }
    
                public Builder clearOneof(
                        com.google.protobuf.Descriptors.OneofDescriptor oneof) {
                    return (Builder) super.clearOneof(oneof);
                }
    
                public Builder setRepeatedField(
                        com.google.protobuf.Descriptors.FieldDescriptor field,
                        int index, Object value) {
                    return (Builder) super.setRepeatedField(field, index, value);
                }
    
                public Builder addRepeatedField(
                        com.google.protobuf.Descriptors.FieldDescriptor field,
                        Object value) {
                    return (Builder) super.addRepeatedField(field, value);
                }
    
                public Builder mergeFrom(com.google.protobuf.Message other) {
                    if (other instanceof Person) {
                        return mergeFrom((Person) other);
                    } else {
                        super.mergeFrom(other);
                        return this;
                    }
                }
    
                public Builder mergeFrom(Person other) {
                    if (other == Person.getDefaultInstance()) return this;
                    if (other.getId() != 0) {
                        setId(other.getId());
                    }
                    if (!other.getName().isEmpty()) {
                        name_ = other.name_;
                        onChanged();
                    }
                    if (other.getAge() != 0) {
                        setAge(other.getAge());
                    }
                    if (other.hasAddr()) {
                        mergeAddr(other.getAddr());
                    }
                    onChanged();
                    return this;
                }
    
                public final boolean isInitialized() {
                    return true;
                }
    
                public Builder mergeFrom(
                        com.google.protobuf.CodedInputStream input,
                        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                        throws java.io.IOException {
                    Person parsedMessage = null;
                    try {
                        parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
                    } catch (com.google.protobuf.InvalidProtocolBufferException e) {
                        parsedMessage = (Person) e.getUnfinishedMessage();
                        throw e.unwrapIOException();
                    } finally {
                        if (parsedMessage != null) {
                            mergeFrom(parsedMessage);
                        }
                    }
                    return this;
                }
    
                private int id_;
    
                /**
                 * <code>optional int32 id = 1;</code>
                 */
                public int getId() {
                    return id_;
                }
    
                /**
                 * <code>optional int32 id = 1;</code>
                 */
                public Builder setId(int value) {
    
                    id_ = value;
                    onChanged();
                    return this;
                }
    
                /**
                 * <code>optional int32 id = 1;</code>
                 */
                public Builder clearId() {
    
                    id_ = 0;
                    onChanged();
                    return this;
                }
    
                private Object name_ = "";
    
                /**
                 * <code>optional string name = 2;</code>
                 */
                public String getName() {
                    Object ref = name_;
                    if (!(ref instanceof String)) {
                        com.google.protobuf.ByteString bs =
                                (com.google.protobuf.ByteString) ref;
                        String s = bs.toStringUtf8();
                        name_ = s;
                        return s;
                    } else {
                        return (String) ref;
                    }
                }
    
                /**
                 * <code>optional string name = 2;</code>
                 */
                public com.google.protobuf.ByteString
                getNameBytes() {
                    Object ref = name_;
                    if (ref instanceof String) {
                        com.google.protobuf.ByteString b =
                                com.google.protobuf.ByteString.copyFromUtf8(
                                        (String) ref);
                        name_ = b;
                        return b;
                    } else {
                        return (com.google.protobuf.ByteString) ref;
                    }
                }
    
                /**
                 * <code>optional string name = 2;</code>
                 */
                public Builder setName(
                        String value) {
                    if (value == null) {
                        throw new NullPointerException();
                    }
    
                    name_ = value;
                    onChanged();
                    return this;
                }
    
                /**
                 * <code>optional string name = 2;</code>
                 */
                public Builder clearName() {
    
                    name_ = getDefaultInstance().getName();
                    onChanged();
                    return this;
                }
    
                /**
                 * <code>optional string name = 2;</code>
                 */
                public Builder setNameBytes(
                        com.google.protobuf.ByteString value) {
                    if (value == null) {
                        throw new NullPointerException();
                    }
                    checkByteStringIsUtf8(value);
    
                    name_ = value;
                    onChanged();
                    return this;
                }
    
                private int age_;
    
                /**
                 * <code>optional int32 age = 3;</code>
                 */
                public int getAge() {
                    return age_;
                }
    
                /**
                 * <code>optional int32 age = 3;</code>
                 */
                public Builder setAge(int value) {
    
                    age_ = value;
                    onChanged();
                    return this;
                }
    
                /**
                 * <code>optional int32 age = 3;</code>
                 */
                public Builder clearAge() {
    
                    age_ = 0;
                    onChanged();
                    return this;
                }
    
                private Addr addr_ = null;
                private com.google.protobuf.SingleFieldBuilderV3<
                        Addr, Addr.Builder, AddrOrBuilder> addrBuilder_;
    
                /**
                 * <code>optional .Addr addr = 4;</code>
                 */
                public boolean hasAddr() {
                    return addrBuilder_ != null || addr_ != null;
                }
    
                /**
                 * <code>optional .Addr addr = 4;</code>
                 */
                public Addr getAddr() {
                    if (addrBuilder_ == null) {
                        return addr_ == null ? Addr.getDefaultInstance() : addr_;
                    } else {
                        return addrBuilder_.getMessage();
                    }
                }
    
                /**
                 * <code>optional .Addr addr = 4;</code>
                 */
                public Builder setAddr(Addr value) {
                    if (addrBuilder_ == null) {
                        if (value == null) {
                            throw new NullPointerException();
                        }
                        addr_ = value;
                        onChanged();
                    } else {
                        addrBuilder_.setMessage(value);
                    }
    
                    return this;
                }
    
                /**
                 * <code>optional .Addr addr = 4;</code>
                 */
                public Builder setAddr(
                        Addr.Builder builderForValue) {
                    if (addrBuilder_ == null) {
                        addr_ = builderForValue.build();
                        onChanged();
                    } else {
                        addrBuilder_.setMessage(builderForValue.build());
                    }
    
                    return this;
                }
    
                /**
                 * <code>optional .Addr addr = 4;</code>
                 */
                public Builder mergeAddr(Addr value) {
                    if (addrBuilder_ == null) {
                        if (addr_ != null) {
                            addr_ =
                                    Addr.newBuilder(addr_).mergeFrom(value).buildPartial();
                        } else {
                            addr_ = value;
                        }
                        onChanged();
                    } else {
                        addrBuilder_.mergeFrom(value);
                    }
    
                    return this;
                }
    
                /**
                 * <code>optional .Addr addr = 4;</code>
                 */
                public Builder clearAddr() {
                    if (addrBuilder_ == null) {
                        addr_ = null;
                        onChanged();
                    } else {
                        addr_ = null;
                        addrBuilder_ = null;
                    }
    
                    return this;
                }
    
                /**
                 * <code>optional .Addr addr = 4;</code>
                 */
                public Addr.Builder getAddrBuilder() {
    
                    onChanged();
                    return getAddrFieldBuilder().getBuilder();
                }
    
                /**
                 * <code>optional .Addr addr = 4;</code>
                 */
                public AddrOrBuilder getAddrOrBuilder() {
                    if (addrBuilder_ != null) {
                        return addrBuilder_.getMessageOrBuilder();
                    } else {
                        return addr_ == null ?
                                Addr.getDefaultInstance() : addr_;
                    }
                }
    
                /**
                 * <code>optional .Addr addr = 4;</code>
                 */
                private com.google.protobuf.SingleFieldBuilderV3<
                        Addr, Addr.Builder, AddrOrBuilder>
                getAddrFieldBuilder() {
                    if (addrBuilder_ == null) {
                        addrBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
                                Addr, Addr.Builder, AddrOrBuilder>(
                                getAddr(),
                                getParentForChildren(),
                                isClean());
                        addr_ = null;
                    }
                    return addrBuilder_;
                }
    
                public final Builder setUnknownFields(
                        final com.google.protobuf.UnknownFieldSet unknownFields) {
                    return this;
                }
    
                public final Builder mergeUnknownFields(
                        final com.google.protobuf.UnknownFieldSet unknownFields) {
                    return this;
                }
    
    
                // @@protoc_insertion_point(builder_scope:Person)
            }
    
            // @@protoc_insertion_point(class_scope:Person)
            private static final Person DEFAULT_INSTANCE;
    
            static {
                DEFAULT_INSTANCE = new Person();
            }
    
            public static Person getDefaultInstance() {
                return DEFAULT_INSTANCE;
            }
    
            private static final com.google.protobuf.Parser<Person>
                    PARSER = new com.google.protobuf.AbstractParser<Person>() {
                public Person parsePartialFrom(
                        com.google.protobuf.CodedInputStream input,
                        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                        throws com.google.protobuf.InvalidProtocolBufferException {
                    return new Person(input, extensionRegistry);
                }
            };
    
            public static com.google.protobuf.Parser<Person> parser() {
                return PARSER;
            }
    
            @Override
            public com.google.protobuf.Parser<Person> getParserForType() {
                return PARSER;
            }
    
            public Person getDefaultInstanceForType() {
                return DEFAULT_INSTANCE;
            }
    
        }
    
        public interface AddrOrBuilder extends
                // @@protoc_insertion_point(interface_extends:Addr)
                com.google.protobuf.MessageOrBuilder {
    
            /**
             * <code>optional string contry = 1;</code>
             */
            String getContry();
    
            /**
             * <code>optional string contry = 1;</code>
             */
            com.google.protobuf.ByteString
            getContryBytes();
    
            /**
             * <code>optional string city = 2;</code>
             */
            String getCity();
    
            /**
             * <code>optional string city = 2;</code>
             */
            com.google.protobuf.ByteString
            getCityBytes();
        }
    
        /**
         * Protobuf type {@code Addr}
         */
        public static final class Addr extends
                com.google.protobuf.GeneratedMessageV3 implements
                // @@protoc_insertion_point(message_implements:Addr)
                AddrOrBuilder {
            // Use Addr.newBuilder() to construct.
            private Addr(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
                super(builder);
            }
    
            private Addr() {
                contry_ = "";
                city_ = "";
            }
    
            @Override
            public final com.google.protobuf.UnknownFieldSet
            getUnknownFields() {
                return com.google.protobuf.UnknownFieldSet.getDefaultInstance();
            }
    
            private Addr(
                    com.google.protobuf.CodedInputStream input,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws com.google.protobuf.InvalidProtocolBufferException {
                this();
                int mutable_bitField0_ = 0;
                try {
                    boolean done = false;
                    while (!done) {
                        int tag = input.readTag();
                        switch (tag) {
                            case 0:
                                done = true;
                                break;
                            default: {
                                if (!input.skipField(tag)) {
                                    done = true;
                                }
                                break;
                            }
                            case 10: {
                                String s = input.readStringRequireUtf8();
    
                                contry_ = s;
                                break;
                            }
                            case 18: {
                                String s = input.readStringRequireUtf8();
    
                                city_ = s;
                                break;
                            }
                        }
                    }
                } catch (com.google.protobuf.InvalidProtocolBufferException e) {
                    throw e.setUnfinishedMessage(this);
                } catch (java.io.IOException e) {
                    throw new com.google.protobuf.InvalidProtocolBufferException(
                            e).setUnfinishedMessage(this);
                } finally {
                    makeExtensionsImmutable();
                }
            }
    
            public static final com.google.protobuf.Descriptors.Descriptor
            getDescriptor() {
                return PersonFactory.internal_static_Addr_descriptor;
            }
    
            protected FieldAccessorTable
            internalGetFieldAccessorTable() {
                return PersonFactory.internal_static_Addr_fieldAccessorTable
                        .ensureFieldAccessorsInitialized(
                                Addr.class, Builder.class);
            }
    
            public static final int CONTRY_FIELD_NUMBER = 1;
            private volatile Object contry_;
    
            /**
             * <code>optional string contry = 1;</code>
             */
            public String getContry() {
                Object ref = contry_;
                if (ref instanceof String) {
                    return (String) ref;
                } else {
                    com.google.protobuf.ByteString bs =
                            (com.google.protobuf.ByteString) ref;
                    String s = bs.toStringUtf8();
                    contry_ = s;
                    return s;
                }
            }
    
            /**
             * <code>optional string contry = 1;</code>
             */
            public com.google.protobuf.ByteString
            getContryBytes() {
                Object ref = contry_;
                if (ref instanceof String) {
                    com.google.protobuf.ByteString b =
                            com.google.protobuf.ByteString.copyFromUtf8(
                                    (String) ref);
                    contry_ = b;
                    return b;
                } else {
                    return (com.google.protobuf.ByteString) ref;
                }
            }
    
            public static final int CITY_FIELD_NUMBER = 2;
            private volatile Object city_;
    
            /**
             * <code>optional string city = 2;</code>
             */
            public String getCity() {
                Object ref = city_;
                if (ref instanceof String) {
                    return (String) ref;
                } else {
                    com.google.protobuf.ByteString bs =
                            (com.google.protobuf.ByteString) ref;
                    String s = bs.toStringUtf8();
                    city_ = s;
                    return s;
                }
            }
    
            /**
             * <code>optional string city = 2;</code>
             */
            public com.google.protobuf.ByteString
            getCityBytes() {
                Object ref = city_;
                if (ref instanceof String) {
                    com.google.protobuf.ByteString b =
                            com.google.protobuf.ByteString.copyFromUtf8(
                                    (String) ref);
                    city_ = b;
                    return b;
                } else {
                    return (com.google.protobuf.ByteString) ref;
                }
            }
    
            private byte memoizedIsInitialized = -1;
    
            public final boolean isInitialized() {
                byte isInitialized = memoizedIsInitialized;
                if (isInitialized == 1) return true;
                if (isInitialized == 0) return false;
    
                memoizedIsInitialized = 1;
                return true;
            }
    
            public void writeTo(com.google.protobuf.CodedOutputStream output)
                    throws java.io.IOException {
                if (!getContryBytes().isEmpty()) {
                    com.google.protobuf.GeneratedMessageV3.writeString(output, 1, contry_);
                }
                if (!getCityBytes().isEmpty()) {
                    com.google.protobuf.GeneratedMessageV3.writeString(output, 2, city_);
                }
            }
    
            public int getSerializedSize() {
                int size = memoizedSize;
                if (size != -1) return size;
    
                size = 0;
                if (!getContryBytes().isEmpty()) {
                    size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, contry_);
                }
                if (!getCityBytes().isEmpty()) {
                    size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, city_);
                }
                memoizedSize = size;
                return size;
            }
    
            private static final long serialVersionUID = 0L;
    
            @Override
            public boolean equals(final Object obj) {
                if (obj == this) {
                    return true;
                }
                if (!(obj instanceof Addr)) {
                    return super.equals(obj);
                }
                Addr other = (Addr) obj;
    
                boolean result = true;
                result = result && getContry()
                        .equals(other.getContry());
                result = result && getCity()
                        .equals(other.getCity());
                return result;
            }
    
            @Override
            public int hashCode() {
                if (memoizedHashCode != 0) {
                    return memoizedHashCode;
                }
                int hash = 41;
                hash = (19 * hash) + getDescriptorForType().hashCode();
                hash = (37 * hash) + CONTRY_FIELD_NUMBER;
                hash = (53 * hash) + getContry().hashCode();
                hash = (37 * hash) + CITY_FIELD_NUMBER;
                hash = (53 * hash) + getCity().hashCode();
                hash = (29 * hash) + unknownFields.hashCode();
                memoizedHashCode = hash;
                return hash;
            }
    
            public static Addr parseFrom(
                    com.google.protobuf.ByteString data)
                    throws com.google.protobuf.InvalidProtocolBufferException {
                return PARSER.parseFrom(data);
            }
    
            public static Addr parseFrom(
                    com.google.protobuf.ByteString data,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws com.google.protobuf.InvalidProtocolBufferException {
                return PARSER.parseFrom(data, extensionRegistry);
            }
    
            public static Addr parseFrom(byte[] data)
                    throws com.google.protobuf.InvalidProtocolBufferException {
                return PARSER.parseFrom(data);
            }
    
            public static Addr parseFrom(
                    byte[] data,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws com.google.protobuf.InvalidProtocolBufferException {
                return PARSER.parseFrom(data, extensionRegistry);
            }
    
            public static Addr parseFrom(java.io.InputStream input)
                    throws java.io.IOException {
                return com.google.protobuf.GeneratedMessageV3
                        .parseWithIOException(PARSER, input);
            }
    
            public static Addr parseFrom(
                    java.io.InputStream input,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws java.io.IOException {
                return com.google.protobuf.GeneratedMessageV3
                        .parseWithIOException(PARSER, input, extensionRegistry);
            }
    
            public static Addr parseDelimitedFrom(java.io.InputStream input)
                    throws java.io.IOException {
                return com.google.protobuf.GeneratedMessageV3
                        .parseDelimitedWithIOException(PARSER, input);
            }
    
            public static Addr parseDelimitedFrom(
                    java.io.InputStream input,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws java.io.IOException {
                return com.google.protobuf.GeneratedMessageV3
                        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
            }
    
            public static Addr parseFrom(
                    com.google.protobuf.CodedInputStream input)
                    throws java.io.IOException {
                return com.google.protobuf.GeneratedMessageV3
                        .parseWithIOException(PARSER, input);
            }
    
            public static Addr parseFrom(
                    com.google.protobuf.CodedInputStream input,
                    com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                    throws java.io.IOException {
                return com.google.protobuf.GeneratedMessageV3
                        .parseWithIOException(PARSER, input, extensionRegistry);
            }
    
            public Builder newBuilderForType() {
                return newBuilder();
            }
    
            public static Builder newBuilder() {
                return DEFAULT_INSTANCE.toBuilder();
            }
    
            public static Builder newBuilder(Addr prototype) {
                return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
            }
    
            public Builder toBuilder() {
                return this == DEFAULT_INSTANCE
                        ? new Builder() : new Builder().mergeFrom(this);
            }
    
            @Override
            protected Builder newBuilderForType(
                    BuilderParent parent) {
                Builder builder = new Builder(parent);
                return builder;
            }
    
            /**
             * Protobuf type {@code Addr}
             */
            public static final class Builder extends
                    com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
                    // @@protoc_insertion_point(builder_implements:Addr)
                    AddrOrBuilder {
                public static final com.google.protobuf.Descriptors.Descriptor
                getDescriptor() {
                    return PersonFactory.internal_static_Addr_descriptor;
                }
    
                protected FieldAccessorTable
                internalGetFieldAccessorTable() {
                    return PersonFactory.internal_static_Addr_fieldAccessorTable
                            .ensureFieldAccessorsInitialized(
                                    Addr.class, Builder.class);
                }
    
                // Construct using com.gp.lock.serizlizer.protobuf.PersonFactory.Addr.newBuilder()
                private Builder() {
                    maybeForceBuilderInitialization();
                }
    
                private Builder(
                        BuilderParent parent) {
                    super(parent);
                    maybeForceBuilderInitialization();
                }
    
                private void maybeForceBuilderInitialization() {
                    if (com.google.protobuf.GeneratedMessageV3
                            .alwaysUseFieldBuilders) {
                    }
                }
    
                public Builder clear() {
                    super.clear();
                    contry_ = "";
    
                    city_ = "";
    
                    return this;
                }
    
                public com.google.protobuf.Descriptors.Descriptor
                getDescriptorForType() {
                    return PersonFactory.internal_static_Addr_descriptor;
                }
    
                public Addr getDefaultInstanceForType() {
                    return Addr.getDefaultInstance();
                }
    
                public Addr build() {
                    Addr result = buildPartial();
                    if (!result.isInitialized()) {
                        throw newUninitializedMessageException(result);
                    }
                    return result;
                }
    
                public Addr buildPartial() {
                    Addr result = new Addr(this);
                    result.contry_ = contry_;
                    result.city_ = city_;
                    onBuilt();
                    return result;
                }
    
                public Builder clone() {
                    return (Builder) super.clone();
                }
    
                public Builder setField(
                        com.google.protobuf.Descriptors.FieldDescriptor field,
                        Object value) {
                    return (Builder) super.setField(field, value);
                }
    
                public Builder clearField(
                        com.google.protobuf.Descriptors.FieldDescriptor field) {
                    return (Builder) super.clearField(field);
                }
    
                public Builder clearOneof(
                        com.google.protobuf.Descriptors.OneofDescriptor oneof) {
                    return (Builder) super.clearOneof(oneof);
                }
    
                public Builder setRepeatedField(
                        com.google.protobuf.Descriptors.FieldDescriptor field,
                        int index, Object value) {
                    return (Builder) super.setRepeatedField(field, index, value);
                }
    
                public Builder addRepeatedField(
                        com.google.protobuf.Descriptors.FieldDescriptor field,
                        Object value) {
                    return (Builder) super.addRepeatedField(field, value);
                }
    
                public Builder mergeFrom(com.google.protobuf.Message other) {
                    if (other instanceof Addr) {
                        return mergeFrom((Addr) other);
                    } else {
                        super.mergeFrom(other);
                        return this;
                    }
                }
    
                public Builder mergeFrom(Addr other) {
                    if (other == Addr.getDefaultInstance()) return this;
                    if (!other.getContry().isEmpty()) {
                        contry_ = other.contry_;
                        onChanged();
                    }
                    if (!other.getCity().isEmpty()) {
                        city_ = other.city_;
                        onChanged();
                    }
                    onChanged();
                    return this;
                }
    
                public final boolean isInitialized() {
                    return true;
                }
    
                public Builder mergeFrom(
                        com.google.protobuf.CodedInputStream input,
                        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                        throws java.io.IOException {
                    Addr parsedMessage = null;
                    try {
                        parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
                    } catch (com.google.protobuf.InvalidProtocolBufferException e) {
                        parsedMessage = (Addr) e.getUnfinishedMessage();
                        throw e.unwrapIOException();
                    } finally {
                        if (parsedMessage != null) {
                            mergeFrom(parsedMessage);
                        }
                    }
                    return this;
                }
    
                private Object contry_ = "";
    
                /**
                 * <code>optional string contry = 1;</code>
                 */
                public String getContry() {
                    Object ref = contry_;
                    if (!(ref instanceof String)) {
                        com.google.protobuf.ByteString bs =
                                (com.google.protobuf.ByteString) ref;
                        String s = bs.toStringUtf8();
                        contry_ = s;
                        return s;
                    } else {
                        return (String) ref;
                    }
                }
    
                /**
                 * <code>optional string contry = 1;</code>
                 */
                public com.google.protobuf.ByteString
                getContryBytes() {
                    Object ref = contry_;
                    if (ref instanceof String) {
                        com.google.protobuf.ByteString b =
                                com.google.protobuf.ByteString.copyFromUtf8(
                                        (String) ref);
                        contry_ = b;
                        return b;
                    } else {
                        return (com.google.protobuf.ByteString) ref;
                    }
                }
    
                /**
                 * <code>optional string contry = 1;</code>
                 */
                public Builder setContry(
                        String value) {
                    if (value == null) {
                        throw new NullPointerException();
                    }
    
                    contry_ = value;
                    onChanged();
                    return this;
                }
    
                /**
                 * <code>optional string contry = 1;</code>
                 */
                public Builder clearContry() {
    
                    contry_ = getDefaultInstance().getContry();
                    onChanged();
                    return this;
                }
    
                /**
                 * <code>optional string contry = 1;</code>
                 */
                public Builder setContryBytes(
                        com.google.protobuf.ByteString value) {
                    if (value == null) {
                        throw new NullPointerException();
                    }
                    checkByteStringIsUtf8(value);
    
                    contry_ = value;
                    onChanged();
                    return this;
                }
    
                private Object city_ = "";
    
                /**
                 * <code>optional string city = 2;</code>
                 */
                public String getCity() {
                    Object ref = city_;
                    if (!(ref instanceof String)) {
                        com.google.protobuf.ByteString bs =
                                (com.google.protobuf.ByteString) ref;
                        String s = bs.toStringUtf8();
                        city_ = s;
                        return s;
                    } else {
                        return (String) ref;
                    }
                }
    
                /**
                 * <code>optional string city = 2;</code>
                 */
                public com.google.protobuf.ByteString
                getCityBytes() {
                    Object ref = city_;
                    if (ref instanceof String) {
                        com.google.protobuf.ByteString b =
                                com.google.protobuf.ByteString.copyFromUtf8(
                                        (String) ref);
                        city_ = b;
                        return b;
                    } else {
                        return (com.google.protobuf.ByteString) ref;
                    }
                }
    
                /**
                 * <code>optional string city = 2;</code>
                 */
                public Builder setCity(
                        String value) {
                    if (value == null) {
                        throw new NullPointerException();
                    }
    
                    city_ = value;
                    onChanged();
                    return this;
                }
    
                /**
                 * <code>optional string city = 2;</code>
                 */
                public Builder clearCity() {
    
                    city_ = getDefaultInstance().getCity();
                    onChanged();
                    return this;
                }
    
                /**
                 * <code>optional string city = 2;</code>
                 */
                public Builder setCityBytes(
                        com.google.protobuf.ByteString value) {
                    if (value == null) {
                        throw new NullPointerException();
                    }
                    checkByteStringIsUtf8(value);
    
                    city_ = value;
                    onChanged();
                    return this;
                }
    
                public final Builder setUnknownFields(
                        final com.google.protobuf.UnknownFieldSet unknownFields) {
                    return this;
                }
    
                public final Builder mergeUnknownFields(
                        final com.google.protobuf.UnknownFieldSet unknownFields) {
                    return this;
                }
    
    
                // @@protoc_insertion_point(builder_scope:Addr)
            }
    
            // @@protoc_insertion_point(class_scope:Addr)
            private static final Addr DEFAULT_INSTANCE;
    
            static {
                DEFAULT_INSTANCE = new Addr();
            }
    
            public static Addr getDefaultInstance() {
                return DEFAULT_INSTANCE;
            }
    
            private static final com.google.protobuf.Parser<Addr>
                    PARSER = new com.google.protobuf.AbstractParser<Addr>() {
                public Addr parsePartialFrom(
                        com.google.protobuf.CodedInputStream input,
                        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
                        throws com.google.protobuf.InvalidProtocolBufferException {
                    return new Addr(input, extensionRegistry);
                }
            };
    
            public static com.google.protobuf.Parser<Addr> parser() {
                return PARSER;
            }
    
            @Override
            public com.google.protobuf.Parser<Addr> getParserForType() {
                return PARSER;
            }
    
            public Addr getDefaultInstanceForType() {
                return DEFAULT_INSTANCE;
            }
    
        }
    
        private static final com.google.protobuf.Descriptors.Descriptor
                internal_static_Person_descriptor;
        private static final
        com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
                internal_static_Person_fieldAccessorTable;
        private static final com.google.protobuf.Descriptors.Descriptor
                internal_static_Addr_descriptor;
        private static final
        com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
                internal_static_Addr_fieldAccessorTable;
    
        public static com.google.protobuf.Descriptors.FileDescriptor
        getDescriptor() {
            return descriptor;
        }
    
        private static com.google.protobuf.Descriptors.FileDescriptor
                descriptor;
    
        static {
            String[] descriptorData = {
                    "\n\014person.proto\"D\n\006Person\022\n\n\002id\030\001 \001(\005\022\014\n\004" +
                            "name\030\002 \001(\t\022\013\n\003age\030\003 \001(\005\022\023\n\004addr\030\004 \001(\0132\005." +
                            "Addr\"$\n\004Addr\022\016\n\006contry\030\001 \001(\t\022\014\n\004city\030\002 \001" +
                            "(\tB0\n\037com.gp.lock.serizlizer.protobufB\rP" +
                            "ersonFactoryb\006proto3"
            };
            com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
                    new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
                        public com.google.protobuf.ExtensionRegistry assignDescriptors(
                                com.google.protobuf.Descriptors.FileDescriptor root) {
                            descriptor = root;
                            return null;
                        }
                    };
            com.google.protobuf.Descriptors.FileDescriptor
                    .internalBuildGeneratedFileFrom(descriptorData,
                            new com.google.protobuf.Descriptors.FileDescriptor[]{
                            }, assigner);
            internal_static_Person_descriptor =
                    getDescriptor().getMessageTypes().get(0);
            internal_static_Person_fieldAccessorTable = new
                    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
                    internal_static_Person_descriptor,
                    new String[]{"Id", "Name", "Age", "Addr",});
            internal_static_Addr_descriptor =
                    getDescriptor().getMessageTypes().get(1);
            internal_static_Addr_fieldAccessorTable = new
                    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
                    internal_static_Addr_descriptor,
                    new String[]{"Contry", "City",});
        }
    
        // @@protoc_insertion_point(outer_class_scope)
    }
    
    
    package com.gp.lock.serizlizer.protobuf;
    
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class Server {
    
        /**
         * @param args
         */
        public static void main(String[] args) throws Exception {
            // TODO Auto-generated method stub
            ServerSocket serverSock = new ServerSocket(3030);
            while (true) {
                Socket sock = serverSock.accept();
                byte[] msg = new byte[256];
                sock.getInputStream().read(msg);
                int msgBodyLen = msg[0];
                System.out.println("msg body len:" + msgBodyLen);
                byte[] msgbody = new byte[msgBodyLen];
                System.arraycopy(msg, 1, msgbody, 0, msgBodyLen);
    
                System.out.println("msgbody = " + new String(msgbody));
                PersonFactory.Person person = PersonFactory.Person.parseFrom(msgbody);
    
                System.out.println("Receive:");
                System.out.println(person);
            }
    
        }
    
    }
    
    
    package com.gp.lock.serizlizer.protobuf;
    
    import com.gp.lock.serizlizer.protobuf.PersonFactory.Addr;
    import com.gp.lock.serizlizer.protobuf.PersonFactory.Person;
    
    import java.net.Socket;
    
    public class Client {
    
        public static void main(String[] args) throws Exception {
            Socket socket = new Socket("127.0.0.1", 3030);
    
            Person.Builder person = Person.newBuilder();
    
            Addr.Builder addr = Addr.newBuilder();
            addr.setContry("china").setCity("shenzhen");
    
            person.setId(1).setAge(12).setName("ccf");
            person.setAddr(addr);
    
            byte[] messageBody = person.build().toByteArray();
    
            System.out.println("messageBody = " + new String(messageBody));
            int headerLen = 1;
            byte[] message = new byte[headerLen + messageBody.length];
            message[0] = (byte) messageBody.length;
            System.arraycopy(messageBody, 0, message, 1, messageBody.length);
            System.out.println("msg len:" + message.length);
            socket.getOutputStream().write(message);
        }
    
    }
    

    结果

    "C:\Program Files\Java\jdk1.8.0_211\bin\java.exe" -Dvisualvm.id=443604366717400 "-javaagent:D:\DevelopTools\IDEA\IntelliJ IDEA 2019.2.2\lib\idea_rt.jar=12578:D:\DevelopTools\IDEA\IntelliJ IDEA 2019.2.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_211\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_211\jre\lib\rt.jar;E:\CODE\Architecture\serializer\target\classes;C:\Users\zwz\.m2\repository\com\thoughtworks\xstream\xstream\1.4.10\xstream-1.4.10.jar;C:\Users\zwz\.m2\repository\xmlpull\xmlpull\1.1.3.1\xmlpull-1.1.3.1.jar;C:\Users\zwz\.m2\repository\xpp3\xpp3_min\1.1.4c\xpp3_min-1.1.4c.jar;C:\Users\zwz\.m2\repository\com\alibaba\fastjson\1.2.31\fastjson-1.2.31.jar;C:\Users\zwz\.m2\repository\io\netty\netty-all\4.1.45.Final\netty-all-4.1.45.Final.jar;C:\Users\zwz\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\zwz\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\zwz\.m2\repository\com\google\protobuf\protobuf-java\3.7.1\protobuf-java-3.7.1.jar" com.gp.lock.serizlizer.protobuf.Server
    msg body len:28
    msgbody =���ccf�"�
    �chinashenzhen
    Receive:
    id: 1
    name: "ccf"
    age: 12
    addr {
      contry: "china"
      city: "shenzhen"
    }
    

    7.3 protostuff

    protostuff是一个基于protobuf实现的序列化方法,它较于protobuf最明显的好处是,在几乎不损耗性能的情况下做到了不用我们写.proto文件来实现序列化。

    package com.gp.lock.serizlizer.protobuf;
    
    import com.dyuproject.protostuff.LinkedBuffer;
    import com.dyuproject.protostuff.ProtostuffIOUtil;
    import com.dyuproject.protostuff.runtime.RuntimeSchema;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class ProtostuffTest {
    
        static RuntimeSchema<Po> poSchema = RuntimeSchema.createFrom(Po.class);
    
        private static byte[] decode(Po po) {
            return ProtostuffIOUtil.toByteArray(po, poSchema, LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
        }
    
        private static Po ecode(byte[] bytes) {
            Po po = poSchema.newMessage();
            ProtostuffIOUtil.mergeFrom(bytes, po, poSchema);
            return po;
        }
    
        public static void main(String[] args) {
            InnerPo innerPo = new InnerPo(1, "InnerPo1");
            List<String> list = new ArrayList<String>();
            list.add("a");
            list.add("b");
            Po po = new Po(1, "Fong", "备注", 24, new int[]{1, 2, 3, 4}, innerPo, list);
            byte[] bytes = decode(po);
            System.out.println(bytes.length);
            Po newPo = ecode(bytes);
            System.out.println(newPo);
        }
    
    }
    

    运行结果

    65
    id:1
    name:Fong
    remark:备注
    age:24
    array:[1, 2, 3, 4]
    innerPo:1-InnerPo1
    more:[a, b]
    

    模式

    package com.asiainfo.dacp.brokerframe.protocol.rpc;
    
    import com.dyuproject.protostuff.LinkedBuffer;
    import com.dyuproject.protostuff.ProtobufIOUtil;
    import com.dyuproject.protostuff.Schema;
    import com.dyuproject.protostuff.runtime.RuntimeSchema;
    import org.objenesis.Objenesis;
    import org.objenesis.ObjenesisStd;
    
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     * @description: Protostuff 序列化与反序列化工具
     * @date : 2020/6/11 17:02
     * @author: zwz
     */
    public class SerializationUtil {
    
        private static Map<Class<?>, Schema<?>> cacheSchema = new ConcurrentHashMap<>();
    
        private static Objenesis objenesis = new ObjenesisStd(true);
    
        public SerializationUtil() {
        }
    
        private static <T> Schema<T> getSchema(Class<T> cls) {
            Schema<T> schema = (Schema<T>) cacheSchema.get(cls);
            if (schema == null) {
                schema = RuntimeSchema.createFrom(cls);
                cacheSchema.put(cls, schema);
            }
            return schema;
        }
    
        public static <T> byte[] serialize(T obj) {
            Class<T> cls = (Class<T>) obj.getClass();
            LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
            try {
                Schema<T> schema = getSchema(cls);
                //序列化:把 obj 按照 schema 模式 写入到 buffer
                return ProtobufIOUtil.toByteArray(obj, schema, buffer);
            } catch (Exception e) {
                throw new IllegalStateException(e.getMessage(), e);
            } finally {
                buffer.clear();
            }
        }
    
        public static <T> T deserialized(byte[] data, Class<T> cls) {
            try {
                T message = objenesis.newInstance(cls);
                Schema<T> schema = getSchema(cls);
                //反序列化:将 data 按 schema 模式重建实例 message
                ProtobufIOUtil.mergeFrom(data, message, schema);
                return message;
            } catch (Exception e) {
                throw new IllegalStateException(e.getMessage(), e);
            }
        }
    }
    

    7.4 Protocol Buffer 的性能好,主要体现在 序列化后的数据体积小 & 序列化速度快,最终使得传输效率高,其原因如下:

    1. 序列化速度快的原因:
    • 编码 / 解码 方式简单(只需要简单的数学运算 = 位移等等)

    • 采用 Protocol Buffer 自身的框架代码 和 编译器 共同完成

    1. 序列化后的数据量体积小(即数据压缩效果好)的原因:
    • 采用了独特的编码方式,如 Varint、Zigzag 编码方式等等

    • 采用 T - L - V 的数据存储方式:减少了分隔符的使用 & 数据存储得紧凑

    8. 序列化技术选型

    技术层面

    1. 序列化空间开销,也就是序列化产生的结果大小,这个影响到传输的性能

    2. 序列化过程中消耗的时长,序列化消耗时间过长影响到业务的响应时间

    3. 序列化协议是否支持跨平台,跨语言。因为现在的架构更加灵活,如果存在异构系统通信需求,那么这个是必须要考虑的

    4. 可扩展性/兼容性,在实际业务开发中,系统往往需要随着需求的快速迭代来实现快速更新,这就要求我们采用的序列化协议基于良好的可扩展性/兼容性,比如在现有的序列化数据结构中新增一个业务字段,不会影响到现有的服务

    5. 技术的流行程度,越流行的技术意味着使用的公司多,那么很多坑都已经淌过并且得到了解决,技术解决方案也相对成熟

    6. 学习难度和易用性

    选型建议

    1. 对性能要求不高的场景,可以采用基于 XML 的 SOAP 协议

    2. 对性能和间接性有比较高要求的场景,那么 Hessian、Protobuf、Thrift、Avro 都可以。

    3. 基于前后端分离,或者独立的对外的 api 服务,选用 JSON 是比较好的,对于调试、可读性都很不错

    4. Avro 设计理念偏于动态类型语言,那么这类的场景使用 Avro 是可以的

    相关文章

      网友评论

          本文标题:序列化

          本文链接:https://www.haomeiwen.com/subject/wfjgtktx.html