什么是序列化?序列化有什么作⽤?
⼀、序列化与反序列化
  序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写⼊到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
  序列化使其他代码可以查看或修改,那些不序列化便⽆法访问的对象实例数据。确切地说,代码执⾏序列化需要特殊的权限:即指定了SerializationFormatter 标志的 SecurityPermission。在默认策略下,通过 Internet 下载的代码或 Internet 代码不会授予该权限;只有本地计算机上的代码才被授予该权限。
通常,对象实例的所有都会被序列化,这意味着数据会被表⽰为实例的序列化数据。这样,能够解释该格式的代码有可能能够确定这些数据的值,⽽不依赖于该成员的可访问性。
  类似地,反序列化从序列化的表⽰形式中提取数据,并直接设置对象状态,这也与可访问性规则⽆关。
对于任何可能包含重要的安全性数据的对象,如果可能,应该使该对象不可序列化。如果它必须为可序列化的,请尝试⽣成特定字段来保存不可序列化的重要数据。如果⽆法实现这⼀点,则应注意该数据会被公开给任何拥有序列化权限的代码,并确保不让任何恶意代码获得该权限。
------------------------- 百度百科上⾯的解释
  我觉得挺好的,我看了很多篇博客,都说的模棱两可,说指堆内存中的java对象数据,通过某种⽅式把对象存储到磁盘⽂件中,或者传递给其他⽹络节点(⽹络传输)。
说序列化就是把对象存储到磁盘中,我认为这种应该叫做数据持久化,不是叫做序列化。 java对象不能直接存储到磁盘中,或不能直接在⽹络上传输,需要转化成另⼀种格式才能,⽽序列化就是把java对象转化成⼀种格式的过程,把java对象序列化,变成⼀种可以存储的形式。
  序列化的作⽤:
    1:对象随着程序的运⾏⽽被创建,然后在不可达时被回收,⽣命周期是短暂的。但是如果我们想长久地把对象的内容保存起来怎么办呢?把它转化为字节序列保存在存储介质上即可。那就需要序列化。
    2:所有可在⽹络上传输的对象都必须是可序列化的,⽐如RMI(remote method invoke,即远程⽅法调⽤),传⼊的参数或返回的对象都是可序列化的,否则会出错;所有需要保存到磁盘的java对象都必须是可序列化的。通常建议:程序创建的每个JavaBean类都实现Serializeable接⼝
    3:进程间传递对象,Android是基于Linux系统,不同进程之间的java对象是⽆法传输,所以我们此
处要对对象进⾏序列化,从⽽实现对象在应⽤程序进程和 ActivityManagerService进程之间传输。
 序列化的实现:
    1:实现Sericalizable接⼝,实现Sericalizable接⼝的时候还要写⼀个SericalizableUID,这个是版本号,JVM会把传进来的字节流中的serialVersionUID与本地实体类中的serialVersionUID进⾏⽐较,如果相同则认为是⼀致的,便可以进⾏反序列化,否则就会报序列化版本不⼀致的异常。如果实现接⼝的时候,没有给定UID,就会使⽤默认的UID,当使⽤默认的UID的时候,jvm每次编译的时候会⽣成⼀个UID,当后⾯程序改了⼀些代码,再次编译的时候会⽣成不同的UID,会导致反序列化失败!所以在实现Sericalizable接⼝的时候,我们⾃⼰给定⼀个固定的UID值,这样就能保证编译完再反序列化的时候的版本⼀致性。所以j能不能成功反序列化,就是看对象中的UID和实体中UID是否⼀致。
    2:实现Externalnalizable接⼝,在类中实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)⽅法,在⽅法中定义类对象⾃定义的序列化和反序列化操作。这样通过对象输出流和对象输⼊流的输⼊输出⽅法序列化和反序列化对象时会⾃动调⽤类中定义的readExternal(ObjectInput in)和writeExternal(ObjectOutput out)⽅法。
    对象的实现序列顺序:
      当前类描述的元数据输出为字节序列;【类定义描述、类中属性定义描述】
javabean是干什么的      超类描述输出为字节序列;【如果超类还有超类,则依次递归,直⾄没有超类】
      从最顶层超类往下,依次输出各类属性值描述,直⾄当前类对象属性值。
      即:从下到上描述类定义,从上往下输出属性值。
      当静态变量和transient关键字修饰的变量不能被序列化;
      反序列化时要按照序列化的顺序重构对象:如先序列化A后序列化B,则反序列化时也要先获取A后获取B,否则报错。
  序列化漏洞:
    反序列化是⼀系列安全问题的根源:攻击者能够将恶意数据序列化并存储到数据库或内存中,当应⽤进⾏反序列化时,应⽤会执⾏到恶意代码。 
    在⾕歌内部,这个缺陷被称为“疯狂的⼩部件 (Mad Gadget)”,外界对它的叫法是 “Java 启⽰录 (Apocalypse)”。
   所以有⼀系列的规范来最⼤化避免: 
      1)对序列化对象执⾏完整性检查或加密,以防⽌恶意对象创建或数据篡改;最常见的例⼦之⼀就是JWT:JWT由3部分组成:Header,Payload,Verify Signature,最后的签名部分其实就是对数据进⾏完整性校验的关键部分,⽤secret对数据部分进⾏哈希计算,随后检查计算出来的哈希值是否和请求中的JWT签名部分的哈希值相同。若两者⼀致则认为数据完整性没有被破坏,若两者有差异则说明数据
被修改过。
      2)在创建对象之前强制执⾏严格的类型约束;
      3)隔离反序列化的代码,使其在⾮常低的特权环境中运⾏;
      4)记录反序列化的例外情况和失败信息,如:传⼊的类型不是预期的类型,或者反序列处理引发的例外情况;      5)限制或监视来⾃于容器或服务器传⼊和传出的反序列化⽹络连接;
      6)监视反序列化,当⽤户持续进⾏反序列化时,对⽤户进⾏警告。
⽬前JAVA常⽤的序列化有protobuf,json,xml,Serializable,hessian,kryo。
  protobuf:⾕歌公司出的⼀款开源项⽬,转码性能⾼,⽀持多语⾔;
  JSON:⽤途最⼴泛,序列化⽅式还衍⽣了阿⾥的fastjson,美团的MSON,⾕歌的GSON等更加优秀的转码⼯具。
      优点:使⽤⽅便。
      缺点:数据冗长,转码性能⼀般。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。