博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java序列化问题
阅读量:5272 次
发布时间:2019-06-14

本文共 4607 字,大约阅读时间需要 15 分钟。

      最近学习xml以及json作为数据源在网络中传输的问题,突然想到java的中自带的序列化和反序列化不正是天然的对象传输方法么,虽然明知道这种方式只在纯java的环境下靠谱,换了其他平台序列化的数据反序列的时候可能会出问题,但是本着学习的态度还是想研究一下。

  序列化流中保存了类的表述信息,比如类的名称,类的签名等,反序列化的一方在读取这些信息之后,就需要根据这些信息加载该类,以便通过反射生成对象,并将后续 的对象数据读取进来。

      开始的时候考虑的是最简单的情况,也就是将服务器和客户端都在本地。换句话说被序列化的类结构对于反序列化端是透明的。这种情况比较简单,用对象流将对象输出到文件中,然后在反序列端再用对象流输入就行了(由于反序列化端的类加载器可以读到这个类的类结构,所以一切都变得很简单)。

  但是这还远远不够,绝大多数情况是客户端对于服务器的类结构一无所知。这时候如果在用上述的方法,由于序列化文件中只有这个对象的信息而没有这个类的信息,导致客户端的类加载器没有办法加载这个类。于是报了经典的CLassNotFound错误。

  然后开始在网上找资料,终于这篇文章帮了大忙,问题的解决方法是重写ObjectOutputStream类的annotateClass方法和ObjectInputStream类的resolveClass方法。第一个方法的作用是在序列化对象的时候将这个对象的类信息一起写入序列化话文件。而第二个方法的作用是在反序列化这个对象的时候可以根究文件中的类信息用类加载器先加载这个类,从而完成反序列话的过程。当然还要写一个自己的类加载器,完成上述的从文件读取类信息的过程。

代码:

package com.ren.test;public class MyClassLoader extends ClassLoader {	   private MyClassLoader()	   {	      super(Thread.currentThread().getContextClassLoader());	   }	   public static Class loadClass(String name, byte[] codeSource)	   {	      Class
c= new MyClassLoader().defineClass(name, codeSource, 0,codeSource.length); System.out.println("load class: " + c.getName() + " over..."); return c; } }

自己的对象输出流

package com.ren.test;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.ObjectOutputStream;import java.io.OutputStream;public class MyObjectOutputStream extends ObjectOutputStream{	public MyObjectOutputStream(OutputStream out) throws IOException {		super(out);		// TODO Auto-generated constructor stub	}	@Override	protected void annotateClass(Class c)throws IOException	   {	      if(c == SiraizeObj.class)	      {	         //计算类的codeSource文件,这里的计算结果是相对于一个classpath	         //的相对路径	         String relativeFile	               = c.getName().replace('.', File.separatorChar)	               + ".class";	         	         //找一个类装载器来获取这个codeSource的输入流	         ClassLoader cl = Thread.currentThread().getContextClassLoader();	         InputStream is = cl.getResourceAsStream(relativeFile);	         byte[] bs = new byte[is.available()];	         is.read(bs);	         //将Student.class文件的内容写入到输出流中,这里这个输出流,也是序列化对象时	         //底层的输出流	         this.writeObject(bs);	      }	   }		}

  自己的输入流

package com.ren.test;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.ObjectStreamClass;public class MyObjectInputStream extends ObjectInputStream {                 public MyObjectInputStream(InputStream is)throws IOException        {           super(is);        }        protected Class resolveClass(ObjectStreamClass osc)              throws IOException, ClassNotFoundException        {           String name = osc.getName();           if(name.startsWith("com.ren.test"))           {              System.out.println("resolve class: " + name);              byte[] codeSource = (byte[])this.readObject();              return MyClassLoader.loadClass(name, codeSource);           }           else           {              return super.resolveClass(osc);           }        }}

测试类

package com.ren.test;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Field;public class Iotest1 {    public static void main(String[] args) {        //write_s();        //read_s();            }    public static void read_s() {        try         {            FileInputStream fis=new FileInputStream("d:/a.dat");            ObjectInputStream ios=new MyObjectInputStream(fis);            Object obj1=ios.readObject();            Class
clazz=obj1.getClass(); Field[] fields=clazz.getDeclaredFields(); for(Field field:fields) { System.out.println(field.getName()); field.setAccessible(true); Object obj_test=field.get(obj1); System.out.println(obj_test.toString()); } ios.close(); fis.close(); } catch (Exception e) { e.printStackTrace(); } } public static void write_s() { SiraizeObj obj=new SiraizeObj("ren","123"); try { FileOutputStream fos=new FileOutputStream("d:/a.dat"); ObjectOutputStream oos=new MyObjectOutputStream(fos); oos.writeObject(obj); oos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }

 

转载于:https://www.cnblogs.com/yelongbupt/p/3510244.html

你可能感兴趣的文章
CSS3 3D Transform
查看>>
js深拷贝
查看>>
http和socket之长连接和短连接区别(转)
查看>>
【HTML】网页中如何让DIV在网页滚动到特定位置时出现
查看>>
文件序列化
查看>>
C++11 中的线程、锁和条件变量
查看>>
HDU 2485 Destroying the bus stations(!最大流∩!费用流∩搜索)
查看>>
Oracle关于用户信息的一些SQL语句
查看>>
2019-02-28处理公司同事无法上网事件记录
查看>>
HTCVive使用
查看>>
Javascript 浏览器检测
查看>>
Java程序员常用工具类库
查看>>
头文件有h和没有h的区别
查看>>
数据库的查询与视图
查看>>
洪涝有源淹没算法及淹没结果分析
查看>>
Flex在使用无线电的button切换直方图横坐标和叙述性说明
查看>>
C++ AMP 介绍(两)
查看>>
C++垃圾回收器的实现
查看>>
(二)数据加密技术
查看>>
Iptables和Firewall-selinux
查看>>