`

如何正确的使用Java序列化技术(转)

阅读更多

  摘要:本文比较全面的介绍了Java 序列化技术方方面面的知识,从序列化技术的基础谈起,
  介绍了Java 序列化技术的机制和序列化技术的原理。并在随后的部分详细探讨了序列化的
  高级主题-如何精确的控制序列化机制。通过阅读该文章,你可以了解如何使用Java 序列
  化机制的方式和正确使用的方法,避免实际编程中对该技术的误用。并能掌握如何高效使用
  该技术来完成特殊的功能。
  关键字:序列化(Serialize)、反序列化(DeSerialize)、类加载(ClassLoad)、指纹技术
  (fingerprint)

1 Java 序列化技术概述
  Java 序列化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从其它地方
  把该Byte 流里的数据读出来。重新构造一个相同的对象。这种机制允许你将对象通过网络
  进行传播,并可以随时把对象持久化到数据库、文件等系统里。Java的序列化机制是RMI、
  EJB、JNNI等技术的技术基础。
  1.1 序列化技术基础
  并非所有的Java 类都可以序列化,为了使你指定的类可以实现序列化,你必须使该类
  实现如下接口:
  java.io.Serializable
  需要注意的是,该接口什么方法也没有。实现该类只是简单的标记你的类准备支持序列
  化功能。我们来看如下的代码:

/** 
  * 抽象基本类,完成一些基本的定义 
  */ 
  public abstract class Humanoid { 
  	protected int noOfHeads; 
  	private static int totalHeads; 
  	public Humanoid() { 
  		this(1); 
  	} 
  	public Humanoid(int noOfHeads) { 
  		if (noOfHeads >10) 
  			throw new Error("Be serious. More than 10 heads?!"); 
  		this.noOfHeads = noOfHeads; 
  		synchronized (Humanoid.class) { 
  			totalHeads += noOfHeads; 
  		} 
  	} 
  	public int getHeadCount() { 
  		return totalHeads; 
  	} 
  } 

 该类的一个子类如下:

/** 
 * Humanoid的实现类,实现了序列化接口 
*/ 
import java.io.*; 
public class Person extends Humanoid 
  implements java.io.Serializable { 
  private String lastName; 
  private String firstName; 
  private transient Thread workerThread; 
  private static int population; 
  public Person(String lastName, String firstName) { 
       this.lastName = lastName; 
       this.firstName = firstName; 
       synchronized (Person.class) { 
            population++; 
              } 
  } 
  public String toString() { 
      return "Person " + firstName + " " + lastName; 
  } 
  static synchronized public int getPopulation() { 
      return population; 
  }
} 

 1.2 对象的序列化及反序列化
  上面的类Person 类实现了Serializable 接口,因此是可以序列化的。我们如果要把一个
  可以序列化的对象序列化到文件里或者数据库里,需要下面的类的支持:
  java.io.ObjectOutputStream
  如何正确的使用Java序列化技术 技术研究系列
  下面的代码负责完成Person类的序列化操作:

/** 
 * Person的序列化类,通过该类把Person写入文件系统里。 
*/ 
import java.io.*; 
public class WriteInstance { 
  public static void main(String [] args) throws Exception { 
      if (args.length != 1) { 
          System.out.println("usage: java WriteInstance file"); 
          System.exit(-1); 
      } 
      FileOutputStream fos = new FileOutputStream(args[0]); 
      ObjectOutputStream oos = new ObjectOutputStream(fos); 
      Person p = new Person("gaoyanbing", "haiger"); 
      oos.writeObject(p); 
  } 
} 

 如果我们要序列化的类其实是不能序列化的,则对其进行序列化时会抛出下面的异常:
  java.io.NotSerializableException
  当我们把Person 序列化到一个文件里以后,如果需要从文件中恢复Person 这个对象,
  我们需要借助如下的类:
  java.io.ObjectInputStream
  从文件里把Person类反序列化的代码实现如下:

/** 
 *Person的反序列化类,通过该类从文件系统中读出序列化的数据,并构造一个 
 * Person对象。 
 */ 
import java.io.*; 
public class ReadInstance { 
  public static void main(String [] args) throws Exception { 
      if (args.length != 1) { 
          System.out.println("usage: java ReadInstance filename"); 
          System.exit(-1); 
      } 
      FileInputStream fis = new FileInputStream(args[0]); 
      ObjectInputStream ois = new ObjectInputStream(fis); 
      Object o = ois.readObject(); 
    System.out.println("read object " + o); 
  } 
} 

 1.3 序列化对类的处理原则
  并不是一个实现了序列化接口的类的所有字段及属性都是可以序列化的。我们分为以下
  几个部分来说明:
  u 如果该类有父类,则分两种情况来考虑,如果该父类已经实现了可序列化接口。则
  其父类的相应字段及属性的处理和该类相同;如果该类的父类没有实现可序列化接
  口,则该类的父类所有的字段属性将不会序列化。
  u 如果该类的某个属性标识为static类型的,则该属性不能序列化;
  u 如果该类的某个属性采用transient关键字标识,则该属性不能序列化;
  需要注意的是,在我们标注一个类可以序列化的时候,其以下属性应该设置为transient
  来避免序列化:
  u 线程相关的属性;
  u 需要访问IO、本地资源、网络资源等的属性;
  u 没有实现可序列化接口的属性;(注:如果一个属性没有实现可序列化,而我们又
  没有将其用transient 标识, 则在对象序列化的时候, 会抛出
  java.io.NotSerializableException异常)。
  1.4 构造函数和序列化
  对于父类的处理,如果父类没有实现序列化接口,则其必须有默认的构造函数(即没有
  参数的构造函数)。为什么要这样规定呢?我们来看实际的例子。仍然采用上面的Humanoid
  和Person 类。我们在其构造函数里分别加上输出语句:

/** 
 * 抽象基本类,完成一些基本的定义 
 */ 
public abstract class Humanoid { 
  protected int noOfHeads; 
  private static int totalHeads; 
  public Humanoid() { 
      this(1); 
      System.out.println("Human's default constructor is invoked"); 
  } 
  public Humanoid(int noOfHeads) { 
      if (noOfHeads >10) 
      throw new Error("Be serious. More than 10 heads?!"); 
      this.noOfHeads = noOfHeads; 
      synchronized (Humanoid.class) { 
                totalHeads += noOfHeads; 
            } 
  } 
  public int getHeadCount() { 
      return totalHeads; 
  } 
} 

 

/** 
 * Humanoid的实现类,实现了序列化接口 
 */ 
import java.io.*; 
public class Person extends Humanoid 
      implements java.io.Serializable { 
  private String lastName; 
  private String firstName; 
  private transient Thread workerThread; 
  private static int population; 
  public Person(String lastName, String firstName) { 
      this.lastName = lastName; 
      this.firstName = firstName; 
      synchronized (Person.class) { 
          population++; 
      } 
      System.out.println("Person's constructor is invoked"); 
  } 
  public String toString() { 
      return "Person " + firstName + " " + lastName; 
  } 
  static synchronized public int getPopulation() { 
      return population; 
  } 
} 

 在命令行运行其序列化程序和反序列化程序的结果为:
  如何正确的使用Java序列化技术 技术研究系列
  可以看到,在从流中读出数据构造Person对象的时候,Person 的父类Humanoid的默认
  构造函数被调用了。当然,这点完全不用担心,如果你没有给父类一个默认构造函数,则编
  译的时候就会报错。
  这里,我们把父类Humanoid做如下的修改:

/** 
 * 抽象基本类,完成一些基本的定义 
 */ 
public class Humanoid implements java.io.Serializable { 
  protected int noOfHeads; 
  private static int totalHeads; 
  public Humanoid() { 
      this(1); 
      System.out.println("Human's default constructor is invoked"); 
  } 
  public Humanoid(int noOfHeads) { 
      if (noOfHeads >10) 
          throw new Error("Be serious. More than 10 heads?!"); 
      this.noOfHeads = noOfHeads; 
      synchronized (Humanoid.class) { 
          totalHeads += noOfHeads; 
      } 
  } 
  public int getHeadCount() { 
      return totalHeads; 
  } 
} 

 我们把父类标记为可以序列化, 再来看运行的结果:
  如何正确的使用Java序列化技术 技术研究系列
  可以看到,在反序列化的时候,如果父类也是可序列化的话,则其默认构造函数也不会
  调用。这是为什么呢?
  这是因为Java 对序列化的对象进行反序列化的时候,直接从流里获取其对象数据来生
  成一个对象实例,而不是通过其构造函数来完成,毕竟我们的可序列化的类可能有多个构造
  函数,如果我们的可序列化的类没有默认的构造函数,反序列化机制并不知道要调用哪个构
  造函数才是正确的。
  1.5 序列化带来的问题
  我们可以看到上面的例子,在Person 类里,其字段population 很明显是想跟踪在一个
  JVM里Person类有多少实例,这个字段在其构造函数里完成赋值,当我们在同一个JVM 里
  序列化Person 并反序列化时,因为反序列化的时候Person 的构造函数并没有被调用,所以
  这种机制并不能保证正确获取Person在一个JVM的实例个数,在后面的部分我们将要详细
  探讨这个问题及给出比较好的解决方案。
  2 控制序列化技术
  2.1 使用readObject 和writeObject方法
  由于我们对于对象的序列化是采用如下的类来实现具体的序列化过程:
  java.io.ObjectOutputStream
  而该类主要是通过其writeObject 方法来实现对象的序列化过程,改类同时也提供了一
  种机制来实现用户自定义writeObject 的功能。方法就是在我们的需要序列化的类里实现一
  如何正确的使用Java序列化技术 技术研究系列
  个writeObject方法,这个方法在ObjectOutputStream序列化该对象的时候就会自动的回调它。
  从而完成我们自定义的序列化功能。
  同样的,反序列化的类也实现了同样的回调机制,我们通过扩展其readObject来实现自
  定义的反序列化机制。
  通过这种灵活的回调机制就解决了上面提出的序列化带来的问题,针对上面的Person
  的问题,我们编写如下的readObject方法就可以彻底避免population计数不准确的问题:

private void readObject(ObjectInputStream ois) 
  throws IOException, ClassNotFoundException 
  { 
  ois.defaultReadObject(); 
  synchronized (Person.class) 
  { 
  population++; 
  } 
  System.out.println("Adjusting population in readObject"); 
  } 

2.2 序列化过程的类版本控制
  本节讨论以下问题:
  u 在对象反序列化过程中如何寻找对象的类;
  u 如果序列化和反序列化两边的类不是同一个版本,如何控制;
  2.2.1 序列化类的寻找机制
  在对象的反序列化过程中,是一定需要被反序列化的类能被ClassLoader 找到的,否则
  在反序列化过程中就会抛出java.lang.ClassNotFoundException 异常。关于ClassLoader 如何
  寻找类,这里就不多说了,可以参考我的另一篇讨论ClassLoader 的文章《在非管理环境下
  如何实现热部署》。我们这里只是关心该序列化对象对应的类是被哪个ClassLoader 给Load
  的。为此,我们修改上面的

 

/** 
  * 修改后的反序列化类 
  */ 
  import java.io.*; 
  public class ReadInstance 
  { 
  public void readPerson(String filename) 
  { 
  如何正确的使用Java序列化技术 技术研究系列 
  try{ 
  FileInputStream fis = new FileInputStream(filename); 
  ObjectInputStream ois = new ObjectInputStream(fis); 
  Object o = ois.readObject(); 
  System.out.println("read object " + o); 
  System.out.println(this.getClass().getClassLoader()); 
  Person person = (Person)o; 
  System.out.println(person.getClass().getClassLoader()); 
  }catch(java.io.IOException ie) 
  { 
  ie.printStackTrace(); 
  }catch(ClassNotFoundException ce) 
  { 
  ce.printStackTrace(); 
  } 
  } 
  public static void main(String [] args) throws Exception 
  { 
  if (args.length != 1) 
  { 
  System.out.println("usage: java ReadInstance filename"); 
  System.exit(-1); 
  } 
  ReadInstance readInstance = new ReadInstance(); 
  readInstance.readPerson(args[0]); 
  } 

 我们主要通过背景为黄色的两行代码查看其类加载器,运行结果如下:
  由此可以看出,序列化类的类加载器正式其反序列化实现类的类加载器。这样的话我们
  就可以通过使最新的Person 类的版本发布为只有该反序列化器的ClassLoader可见。而较旧
  的版本则不为该ClassLoader 可见的方法来避免在反序列化过程中类的多重版本的问题。当
  然,下面就类的版本问题我们还要做专门的探讨。
  如何正确的使用Java序列化技术 技术研究系列
  2.2.2 序列化类多重版本的控制
  如果在反序列化的JVM 里出现了该类的不同时期的版本,那么反序列化机制是如何处
  理的呢?
  为了避免这种问题,Java的序列化机制提供了一种指纹技术,不同的类带有不同版本的
  指纹信息,通过其指纹就可以辨别出当前JVM 里的类是不是和将要反序列化后的对象对应
  的类是相同的版本。该指纹实现为一个64bit的long 类型。通过安全的Hash算法(SHA-1)
  来将序列化的类的基本信息(包括类名称、类的编辑者、类的父接口及各种属性等信息)处
  理为该64bit的指纹。我们可以通过JDK自带的命令serialver来打印某个可序列化类的指纹
  信息。如下:
  当我们的两边的类版本不一致的时候,反序列化就会报错:
  如何正确的使用Java序列化技术 技术研究系列
  解决之道:从上面的输出可以看出,该指纹是通过如下的内部变量来提供的:
  private static final long serialVersionUID;
  如果我们在类里提供对该属性的控制,就可以实现对类的序列化指纹的自定义控制。为
  此,我们在Person 类里定义该变量:
  private static final long serialVersionUID= 6921661392987334380L;
  则当我们修改了Person 类,发布不同的版本到反序列化端的JVM,也不会有版本冲突
  的问题了。需要注意的是,serialVersionUID 的值是需要通过serialver 命令来取得。而不能
  自己随便设置,否则可能有重合的。
  需要注意的是,手动设置serialVersionUID 有时候会带来一些问题,比如我们可能对类
  做了关键性的更改。引起两边类的版本产生实质性的不兼容。为了避免这种失败,我们需要
  知道什么样的更改会引起实质性的不兼容,下面的表格列出了会引起实质性不兼容和可以忽
  略(兼容)的更改:
  更改类型 例子
  兼容的更改
  u 添加属性(Adding fields)
  u 添加/删除类(adding/removing classes)
  u 添加/删除writeObject/readObject方法(adding/removing
  writeObject/readObject)
  u 添加序列化标志(adding Serializable)
  u 改变访问修改者(changing access modifier)
  u 删除静态/不可序列化属性(removing static/transient from
  a field)
  不兼容的更改
  u 删除属性(Deleting fields)
  u 在一个继承或者实现层次里删除类(removing classes in a
  hierarchy)
  u 添加静态/不可序列化字段(adding static/transient to a
  field)
  u 修改简单变量类型(changing type of a primitive)
  u switching between Serializable or Externalizable
  u 删除序列化标志(removing Serializable/Externalizable)
  u 改变readObject/writeObject对默认属性值的控制(changing
  whether readObject/writeObject handles default field
  data)
  u adding writeReplace or readResolve that produces
  objects incompatible with older versions
  另外,从Java 的序列化规范里并没有指出当我们对类做了实质性的不兼容修改后反序
  列化会有什么后果。并不是所有的不兼容修改都会引起反序列化的失败。比如,如果我们删
  除了一个属性,则在反序列化的时候,反序列化机制只是简单的将该属性的数据丢弃。从
  JDK 的参考里,我们可以得到一些不兼容的修改引起的后果如下表:
  如何正确的使用Java序列化技术 技术研究系列
  不兼容的修改 引起的反序列化结果
  删除属性
  (Deleting a field) Silently ignored
  在一个继承或者实现层次里删除类
  (Moving classes in inheritance
  hierarchy)
  Exception
  添加静态/不可序列化属性
  (Adding static/transient)
  Silently ignored
  修改基本属性类型
  (Changing primitive type)
  Exception
  改变对默认属性值的使用
  (Changing use of default field data)
  Exception
  在序列化和非序列化及内外部类之间切换
  (Switching Serializable and
  Externalizable)
  Exception
  删除Serializable或者Externalizable标志
  (Removing Serializable or
  Externalizable)
  Exception
  返回不兼容的类
  (Returning incompatible class)
  Depends on incompatibility
  2.3 显示的控制对属性的序列化过程
  在默认的Java 序列化机制里,有关对象属性到byte 流里的属性的对应映射关系都是自
  动而透明的完成的。在序列化的时候,对象的属性的名称默认作为byte 流里的名称。当该
  对象反序列化的时候,就是根据byte 流里的名称来对应映射到新生成的对象的属性里去的。
  举个例子来说。在我们的一个Person对象序列化的时候,Person的一个属性firstName就作
  为byte 流里该属性默认的名称。当该Person 对象反序列化的时候,序列化机制就把从byte
  流里得到的firstName 的值赋值给新的Person 实例里的名叫firstName的属性。
  Java的序列化机制提供了相关的钩子函数给我们使用,通过这些钩子函数我们可以精确
  的控制上述的序列化及反序列化过程。ObjectInputStream的内部类GetField提供了对把属性
  数据从流中取出来的控制,而ObjectOutputStream的内部类PutField则提供了把属性数据放
  入流中的控制机制。就ObjectInputStream来讲,我们需要在readObject方法里来完成从流中
  读取相应的属性数据。比如我们现在把Person 类的版本从下面的表一更新到表二:

/** 
  * 修改前的老版本Person类,为了简化,我们删除了所有无关的代码 
  */ 
  import java.io.*; 
  public class Person extends Humanoid 
  implements java.io.Serializable 
  { 
  private String lastName; 
  如何正确的使用Java序列化技术 技术研究系列 
  private String firstName; 
  private static final long serialVersionUID =6921661392987334380L; 
  private Person() 
  { 
  } 
  public Person(String lastName, String firstName) 
  { 
  this.lastName = lastName; 
  this.firstName = firstName; 
  } 
  public String toString() 
  { 
  return "Person " + firstName + " " + lastName; 
  } 
  } 

 

/** 
  * 修改后的Person类,我们将firstName和lastName变成了fullName 
  */ 
  import java.io.*; 
  public class Person extends Humanoid 
  implements java.io.Serializable 
  { 
  private String fullName; 
  private static final long serialVersionUID =6921661392987334380L; 
  private Person() 
  { 
  } 
  public Person(String fullName) 
  { 
  this.lastName = fullName; 
  } 
  public String toString() 
  { 
  return "Person " + fullName; 
  } 
  } 

为此,我们需要编写Person类的readObject方法如下: 

private void readObject(ObjectInputStream ois) 
  throws IOException,ClassNotFoundException 
  { 
  ObjectInputStream.GetField gf = ois.readFields(); 
  fullName = (String) gf.get("fullName", null); 
  if (fullName == null) 
  { 
  String lastName = (String) gf.get("lastName", null); 
  如何正确的使用Java序列化技术 技术研究系列 
  String firstName = (String) gf.get("firstName", null); 
  if ( (lastName == null) || (firstName == null)) 
  { 
  throw new InvalidClassException("invalid Person"); 
  } 
  fullName = firstName + " " + lastName; 
  } 
  } 

  我们的执行顺序是:
  1) 编译老的Person及所有类;
  2) 将老的Person序列化到文件里;
  3) 修改为新版本的Person类;
  4) 编译新的Person类;
  5) 反序列化Person;
  执行结果非常顺利,修改后的反序列化机制仍然正确的从流中获取了旧版本Person 的
  属性信息并完成对新版本的Person的属性赋值。
  使用ObjectInputStream的readObject 来处理反序列化的属性时,有两点需要注意:
  u 一旦采用自己控制属性的反序列化,则必须完成所有属性的反序列化(即要给所有
  属性赋值);
  u 在使用内部类GetField 的get 方法的时候需要注意,如果get 的是一个既不在老版
  本出现的属性,有没有在新版本出现的属性,则该方法会抛出异常:
  IllegalArgumentException: no such field,所以我们应该在一个try块里
  来使用该方法。
  同理,我们可以通过writeObject 方法来控制对象属性的序列化过程。这里就不再一一
  举例了,如果你有兴趣的话,可以自己实现Person 类的writeObject 方法,并且使用
  ObjectOutputStream的内部类PutField来完成属性的手动序列化操作。
  3 总结
  Java 序列化机制提供了强大的处理能力。一般来讲,为了尽量利用Java 提供的自动化
  机制,我们不需要对序列化的过程做任何的干扰。但是在某些时候我们需要实现一些特殊的
  功能,比如类的多版本的控制,特殊字段的序列化控制等。我们可以通过多种方式来实现这
  些功能:
  u 利用序列化机制提供的钩子函数readObject和writeObject;
  u 覆盖序列化类的metaData 信息;
  如何正确的使用Java序列化技术 技术研究系列
  u 使类实现Externalizable 接口而不是实现Serializable接口。
  关于Externalizable 接口更多的介绍,可以参考JDK 的帮助提供的详细文档,同时也可
  以快速参考《Thinking in Java》这本书第十章-Java IO系统的介绍。
  参考资料:
  1、 SUN关于Java 的虚拟机规范《The Java Virtual Machine Specification》;
  2、 《Thinking in Java》;
  3、 《基于Java平台的组件化开发技术》。
  关于作者:
  高雁冰(网名Haiger 或者tuskrabbit)是深圳华为技术有限公司的商业网络业务部总体设计
  部架构设计师,拥有多个大型企业应用系统(百万、千万用户级)的架构设计经验。个人研
  究方向主要集中在J2EE平台的全程建模技术、WEB工程技术及企业应用集成(EAI)的咨
  询和实施上。可以通过gaoyb@huawei.com与他取得联系。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/qingtanlang/archive/2008/03/30/2231377.aspx

分享到:
评论

相关推荐

    如何正确的使用Java序列化技术

    ### 如何正确使用Java序列化技术 #### 技术研究系列 **摘要:** 本文将深入探讨Java序列化技术的各个方面,从基础知识入手,逐步展开对序列化技术机制与原理的介绍。此外,还将深入讨论如何精准控制序列化机制,...

    Java对象序列化标准最新版

    ### Java对象序列化标准知识点详解 #### 一、系统架构概览 **1.1 概览** Java 对象序列化是一种将Java对象的...以上内容涵盖了Java序列化标准的关键知识点,深入了解这些概念有助于更好地理解和应用Java序列化技术。

    java序列化原理与算法

    ### Java序列化原理与算法详解 #### 序言 在现代软件开发中,尤其是在网络通信和数据持久化领域,对象的序列化与反序列化扮演着至关重要的角色。Java作为一种广泛应用的编程语言,提供了强大的内置支持来实现序列化...

    Java_序列化的高级认识

    Java序列化作为Java技术体系中的一个重要组成部分,其核心功能在于能够将Java对象转换成字节流,从而实现对象的持久化存储或是通过网络传输。然而,序列化的应用远不止于此,它还涉及到一系列复杂的概念和技术细节,...

    Netty服务端与客户端依靠Java序列化传输数据

    在使用Java序列化时,需要确保服务端和客户端都理解并遵循相同的序列化协议,以保证数据正确传输和解析。 8. **异常处理**: 在数据传输过程中,可能会遇到各种异常,如序列化或反序列化失败,网络中断等。合理的...

    Java序列化和反序列化

    ### Java序列化与反序列化的深入解析 #### 序列化的功能与意义 序列化是Java编程语言中的一项核心功能,其主要目的是将对象的状态转换为可以存储或传输的格式,便于持久化保存或网络传输。序列化并不涉及对象的...

    基于java序列化的Netty编解码技术

    Java序列化是Java平台内建的一种对象...总之,基于Java序列化的Netty编解码技术在处理Java对象的网络传输时提供了便利,但同时也存在性能和安全等方面的挑战。合理使用和优化这一技术,可以提升系统的稳定性和效率。

    Java对象的序列化和反序列化实践

    为了确保不同版本的类能够正确地进行序列化和反序列化,Java引入了`serialVersionUID`。这是一个用于标识类序列化版本的特殊字段。如果不显式声明,JVM会自动生成一个默认值。但是,当类结构改变时,应该手动更新此...

    java序列化深度探讨

    总的来说,Java序列化是一种强大且灵活的技术,但需要谨慎使用,尤其是在处理敏感数据和实现分布式系统时。理解序列化的原理以及如何正确使用`Serializable`和`Externalizable`接口,对于开发高质量的Java应用程序至...

    深入剖析Java序列化:挑战复杂的面试题与详细解析

    Java序列化是Java平台提供的一种将对象转换为字节流,以便存储到磁盘或在网络中传输的技术。它是Java核心概念的重要组成部分,特别是在面试中,深入理解和熟练掌握Java序列化能够展示出程序员的高级技能。 1. **...

    java反序列香草

    Java反序列化是Java编程语言中的一个特性,允许将对象的状态转换为字节流,然后在需要时恢复这些状态。这个过程通常用于持久化对象,网络传输或在不同应用程序之间共享数据。然而,由于设计上的漏洞,反序列化也可能...

    序列化和反序列化dll文件和proto

    总的来说,理解和掌握序列化和反序列化技术对于任何IT专业人员来说都是至关重要的,无论是在处理DLL文件以实现模块化开发,还是在使用Proto进行高效的数据交换。正确使用这些技术能够提高代码的可维护性、减少网络...

    java序列化(Serializable)的作用和反序列化.pdf

    Java序列化是Java平台提供的一种持久化机制,它允许将对象的状态转换为字节流,以便存储到磁盘、数据库中或通过网络进行传输。序列化对于数据存储、跨网络对象传输以及远程方法调用(RMI)等场景非常有用。 1. **...

    Java 序列化的秘密(高清PDF中文版)

    ### Java序列化的秘密 #### 为什么需要序列化 在探讨序列化之前,我们需要理解序列化产生的背景及其必要性。简而言之,Java程序本质上是由进程和内存构成的系统,在这个系统中,进程根据定义好的类生成一系列实例...

    对象的序列化和反序列化

    对象的序列化和反序列化是Java编程语言中重要的概念,它们主要用于持久化对象的状态,以便在需要时能够恢复。序列化是将一个对象转换为字节流的过程,而反序列化则是将字节流还原为原来的对象。这两个过程在许多场景...

    序列化与反序列化Demo

    2. 版本问题:当类的结构发生变化时,序列化的对象可能无法正确地反序列化。为了解决这个问题,可以使用`serialVersionUID`字段。 3. 性能开销:序列化和反序列化过程可能会消耗一定的时间和内存资源。 此外,Java...

    通过socket传递java对象(对象序列化)

    总结来说,通过Socket传递Java对象主要依赖于对象序列化技术。理解这一过程对于进行Java网络编程和构建分布式系统至关重要。在实际应用中,我们需要注意安全性和版本兼容性,并且可以选择适合的工具来简化工作。

    Java中序列化学习笔记/序列和反序列化的实现

    Java中的序列化是一种将对象的状态转化为可存储或可传输的形式的技术。这主要涉及到将对象转换为字节流,以便可以在网络上发送,或者保存到文件系统中,之后再通过反序列化恢复为原来的对象状态。序列化对于实现跨...

    Java序列化与反序列化三种格式存取

     正确使用序列化机制  一般而言,要使得一个类可以序列化,只需简单实现java.io.Serializable接口即可(还要实现无参数的构造方法)。该接口是一个标记式接口,它本身不包含任何内容,实现了该接口则表示这个类...

Global site tag (gtag.js) - Google Analytics