Java序列化机制详解

Java对象序列化是JDK1.1中引入的机制,用于将Java对象的状态转换为字节数组,以便存储和传输,并且可以将字节数组转换回Java对象原有的状态。Java对象序列化的思想是:“冻结”Java对象状态,写入磁盘或者通过网络传输,然后“解冻”Java对象状态,恢复出Java对象状态。

本文主要分三个部分:

1、Java对象序列化和反序列化的基本流程;

2、Java序列化机制使用过程中需要注意的一些关键点;

3、Java序列化机制一些不常被使用的功能;


Java对象下序列化和反序列化的基本流程:

Java对象的序列化流程:


下面给出writeHierarchy的部分代码:

if (osc.hasMethodWriteObject()) {
    final Method method = osc.getMethodWriteObject();
    try {
        method.invoke(object, new Object[] { this });
        executed = true;
    } catch (InvocationTargetException e) {
        Throwable ex = e.getTargetException();
        if (ex instanceof RuntimeException) {
            throw (RuntimeException) ex;
        } else if (ex instanceof Error) {
            throw (Error) ex;
        }
        throw (IOException) ex;
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e.toString());
    }
}

if (executed) {
    drain();
    output.writeByte(TC_ENDBLOCKDATA);
} else {
    // If the object did not have a writeMethod, call
    // defaultWriteObject
    defaultWriteObject();
}


可以看到在这部分代码中,会判断Java对象是否重写了writeObject方法,如果重写了writeObject方法,则通过反射调用writeObject方法,否则调用defaultWriteObject方法。

Java对象的反序列化流程:

下面给出readObjectForClass的详细代码:

if (targetClass == null || !mustResolve) {
    readMethod = null;
} else {
    readMethod = classDesc.getMethodReadObject();
}
if (readMethod != null) {
    // We have to be able to fetch its value, even if it is private
    readMethod.setAccessible(true);
    try {
        readMethod.invoke(object, this);
    } catch (InvocationTargetException e) {
        Throwable ex = e.getTargetException();
        if (ex instanceof ClassNotFoundException) {
            throw (ClassNotFoundException) ex;
        } else if (ex instanceof RuntimeException) {
            throw (RuntimeException) ex;
        } else if (ex instanceof Error) {
            throw (Error) ex;
        }
        throw (IOException) ex;
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e.toString());
    }
} else {
    defaultReadObject();
}
if (hadWriteMethod) {
    discardData();
}


可以看到在这部分代码中,会判断Java对象是否重写了readObject方法,如果重写了readObject方法,则通过反射调用readObject方法,否则调用defaultReadObject方法。


Java序列化机制使用过程中需要注意的一些关键点:

1、序列化只针对对象状态,不针对类状态,所以,序列化的过程中是不会保存静态变量的;

2、如果子类实现了Serializable接口,父类没有实现Serializable接口,那么在子类的序列化过程中只会保存子类中定义的成员变量;

3、使用transient关键字修饰的成员变量,在序列化过程中不会被保存,在反序列化过程中会被置为默认值;


Java序列化机制一些不常被使用的功能:
1、Java序列化机制允许重构:Java序列化允许一定数量的类变化,甚至在经过类重构之后,ObjectInputStream仍然可以将Java对象恢复出来,Java Object Serialization规范可以自动管理的关键任务是:a、在类中添加新字段;b、将字段从static改为非static;c、将字段从transient改为非transient;序列化会使用一个hash值,即serialVersionUID,这个hash值根据源文件中几乎所有内容(字段类型,字段名称,方法名称等等)计算得到。为了使Java运行时相信重构后和重构前的Java类是一致的,需要保证不同版本的Java类的serialVersionUID是相等的,最初版本的Java类的serialVersionUID可以通过运行JDK serialver命令得到。
2、使序列化过程变得安全:Java的序列化过程是将对象的状态以二进制格式保存到磁盘上,或者通过网络传输,可以很轻易地看到Java对象的内容。为了保证Java对象内容的安全性,有两类方法:1、hook Java对象的序列化过程,在上文分析Java对象序列化的基本流程时有提到可以重写对象的writeObject方法,可以在writeObject方法中进行数据模糊化操作,但是,这类方法只是对数据进行了模糊化操作,并不能保证数据不会被看到;b、对Java对象进行签名和密封,将Java对象放入javax.crypto.SealedObject或者java.security.SignedObject包装器中,将对象包装在SealedObject中,可以围绕原对象简历一个“包装盒”,需要使用对称秘钥才能打开,秘钥需要单独管理;SignedObject和SealedObject功能类似,用于数据验证。




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java序列化机制Java语言中的一种重要机制,它可以将Java对象转换为字节序列,以便在网络上传输或在文件中存储。Java序列化机制由两个部分组成:序列化和反序列化。 1. 序列化 序列化是将Java对象转换为字节序列的过程,这个过程可以通过将对象写入输出流来完成。Java提供了两个主要的序列化类:ObjectOutputStream和ObjectInputStream。 ObjectOutputStream类是用来将Java对象写入输出流的,它可以将Java对象转换为字节序列,并将字节序列写入输出流。序列化的过程中,ObjectOutputStream会将对象的类信息和实例数据都写入输出流中。 2. 反序列化序列化是将字节序列转换为Java对象的过程,这个过程可以通过读取输入流来完成。Java提供了两个主要的反序列化类:ObjectInputStream和ObjectOutputStream。 ObjectInputStream类是用来从输入流中读取字节序列的,并将其转换为Java对象。反序列化的过程中,ObjectInputStream会从输入流中读取对象的类信息和实例数据,并重新创建Java对象。 3. 序列化机制的实现原理 Java序列化机制的实现原理是通过将Java对象转换为字节序列并将其写入输出流中,然后通过读取输入流将字节序列转换为Java对象。 Java序列化机制的实现过程中,所有的类都必须实现Serializable接口。这个接口没有任何方法,只是标识了该类可以被序列化Java序列化机制还需要注意一些问题,比如序列化的版本号、序列化的安全性、序列化的性能等。为了提高序列化的性能,可以使用一些优化技巧,比如使用transient关键字防止某些字段被序列化、使用Externalizable接口替代Serializable接口等。 总之,Java序列化机制Java语言中非常重要的一种机制,它可以实现Java对象的跨平台传输和持久化存储。在开发中,需要注意序列化的版本号、安全性和性能等问题,以确保程序的正确性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值