对于同一个socket,如果调用两次就会抛出StreamCorruptedException

如果你使用socket,并通过对象输入/输出流来处理的话,并且已经对某个socket调用了一次getInputStream时,但又需要把这个socket的相关信息作为参数传递给别的对象时,应注意:不用直接把socket传过去,应该把对应的ObjectInputStream或ObjectOutputStream对象传递过去。

调用getInputStream方法就会读取标示头信息。用缺省的serializetion的实现时,一个ObjectOutputStream的构造和一个ObjectInputStream的构造必须一一对应.ObjectOutputStream的构造函数会向输出流中写入一个标识头,而ObjectInputStream会首先读入这个标识头.因此,多次以追加方式向一个文件中写入object时,该文件将会包含多个标识头.所以用ObjectInputStream来deserialize这个ObjectOutputStream时,将产生StreamCorruptedException.

==============================

使用ObjectStream会出现的问题

1. ObjectInputStream与ObjectOutputStream的顺序问题

在网络通讯中,主机与客户端若使用ObjectInputStream与ObjectOutputStream建立对象通讯,必须注意声明此两个对象的顺序。

如:

主机端先建立ObjectInputStream后建立ObjectOutputStream,则对应地客户端要先建立ObjectOutputStream后建立ObjectInputStream,否则会造成两方互相等待数据而导致死锁。

原因是建立ObjectInputStream对象是需要先接收一定的header数据,接收到这些数据之前会处于阻塞状态。以下为JAVA API文档的说明

Creates an ObjectInputStream that reads from the specified InputStream.

A serialization stream header is read from the stream and verified.

This constructor will block until the corresponding ObjectOutputStream

has written and flushed the header.

故而为了防止这种死锁状态,通讯两方的ObjectInputStraem,ObjectOutputStream必须注意顺序对应使用。

2. ObjectInputStream接收到非ObjectOutputStream数据的问题

在使用ObjectInputStream与ObjectOutputStream对象通讯的通讯双方,假设客户端程序出现错误,发送了非ObjectOutputStream封装发送的数据(比如发送一个数字或字符串到主机),则主机端的ObjectInputStream接收到错误数据后不能自动纠正,会一直接收数据而处于阻塞状态,从而导致通讯失败。尚未找到解决方法。目前想的办法为写自己的ObjectStream类。

3. 解决版本问题

使用ObjectStream的时候会额外发送一个关于对象的序列号

static final long serialVersionUID = ....

手动加入此域则可避免版本差异导致的问题。

对象序列号的计算可用SDK的serialver计算。

======================================

ObjectInputStream ObjectOutputStream

ObjectOutputStream和ObjectInputStream

--ObjectOutputStream

ObjectInputStream 类恢复以前使用 ObjectOutputStream 类序列化后的基本类型数据和对象。

ObjectOutputStream 和 ObjectInputStream 分别利用 FileOutputStream 和 FileInputStream 能支持应用程序实现对象图象的稳定存储。

ObjectInputStream 可用于恢复以前序列化过的对象。另外其它一些情况也使用此类,诸如使用一个 Socket 在主机间传递对象时,

或在远程通讯系统中为实现参数和参变量的通讯而进行对象传递时。

ObjectInputStream 保证从流中创建的图象中的所有对象的类型与 Java 虚拟机中出现的类匹配。使用标准机制按需装载相应类。

只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能从流中读取。使用 readObject 方法从该流中

读取一个对象。 Java 的安全造型应该用于获取期望类型。在 Java 中, 串和数组都是对象且可当作是序列化过程中的对象。

读取时,它们需要转换为所需类型。

另外基类型也可使用 DataInput 中的正确方法从该流中读取。

对象的缺省逆序列化机制将每个域的内容恢复为它被写入时的值和类型。逆序列化过程中忽略申明为暂时的或静态的域。

对其它对象的引用促使那些对象必须从流中读取。使用引用共享机制正确地恢复对象的图象。逆序列化时总是分配新对象,

防止重写已存在的对象。

读取一个对象同运行一个新对象的构造子类似。为该对象分配的内存初始化为空(NULL)。为非序列化类调用无参构造子,

然后将序列化类的域从该流中恢复,恢复从最接近 java.lang.object 的序列化对象开始,到指定对象结束。

例如读取在示例中写入 ObjectOutputStream 中的流:

FileInputStream istream = new FileInputStream("t.tmp");

ObjectInputStream p = new ObjectInputStream(istream);

int i = p.readInt();

String today = (String)p.readObject();

Date date = (Date)p.readObject();

istream.close();

类通过实现 java.io.Serializable 或 java.io.Externalizable 接口来控制它们的序列化。

实现序列化接口可以使对象能保存和恢复它的完整状态,可以使类在写入流和从流中读取的期间内进行改进。

它自动地遍历对象间的引用,保存和恢复完整图象。在序列化和逆序列化处理过程中需要特定句柄的可序列化类,

必须实现如下这两个方法:

private void writeObject(java.io.ObjectOutputStream stream)

throws IOException;

private void readObject(java.io.ObjectInputStream stream)

throws IOException, ClassNotFoundException;

利用 writeObjectmethod 方法将一个特殊类的对象的状态写入某流后,相应的 readObject 方法将负责读取和恢复这些数据。

此方法不必关心状态是属于它的父类还是子类。 从 ObjectInputStream 读取数据恢复单个域的状态,并将之赋给该对象的恰当域。

使用 DataInput 方法读取基本数据类型。

序列化操作对没有实现 java.io.Serializable 接口的对象,不读取或分配它的域值。非序列化对象的子类可以是序列化的。

在这种情况下,非序列化类必须有一个无参构造子,使它的域能使用此构造子完成初始化。 在此情况下,

子类负责保存和恢复非序列化类的状态。通常情况父类的域是可存储的(公有的、包或保护的),

或存在用于恢复它的状态的可使用的获取或设置方法。

ObjectInputStream 能获取逆序列化一个对象期间出现的任一异常,一旦出现异常,则放弃读过程。

实现外部接口可以使对象完全控制此对象序列化形式的内容和格式。

调用外部接口的方法:writeExternal 和 readExternal 保存和恢复对象状态。当一个类实现了这些方法时,

它们就能使用 ObjectOutput 和 ObjectInput 方法的所有方法写入或读取它们自己的状态。对象负责管理它出现的相应版本。

ObjectOutputStream

public class ObjectOutputStream

extends OutputStream

implements ObjectOutput, ObjectStreamConstants

类 ObjectOutputStream 将 Java 对象中的基本数据类型和图元写入到一个 OutputStream 对象中。可使用 ObjectInputStream 读取这些对象。

另外使用此流对应的文件能存储这些对象。如果该流是一个网络通讯流,则在另一台主机或另一个处理机上可重建这些对象。

只有支持 java.io.Serializable 接口的对象才能被写入该流。对每个可序列化的对象进行编码,包括相应类的名称和标记,

对象的属性和数组值,以及初始化对象时引用的任何其它对象等。

使用 writeObject 将一个对象写入该流。任一对象,包括串和数组,均采用 writeObject 方法被写入。

也能将多个对象或基类型对象写入此流。反过来,必须以这些对象被写入的相同类型和相同顺序,

从相应的 ObjectInputstream 流中读回这些对象。

基类型也可使用 DataOutput 中的正确方法写入此流。串对象也可使用 writeUTF 方法写入。

一个对象的缺省序列化机制将写入对象的类,类标记和所有的非暂时的和非静态的属性值。

其它对象(除暂时的或静态的属性)的引用也将促使以上这些对象被写入。 使用共享机制,对单一对象的多次引用进行编码,

以至对象的图元能被存储为与它原来写入时有相同的形状。

例如写入一个对象,此对象能从 ObjectInputStream 中读出:

FileOutputStream ostream = new FileOutputStream("t.tmp");

ObjectOutputStream p = new ObjectOutputStream(ostream);

p.writeInt(12345);

p.writeObject("Today");

p.writeObject(new Date());

p.flush();

ostream.close();

在序列化处理过程中需要特定句柄的类,必须使用如下这些恰当的标记实现特定的方法:

private void readObject(java.io.ObjectInputStream stream)

throws IOException, ClassNotFoundException;

private void writeObject(java.io.ObjectOutputStream stream)

throws IOException

writeObject 方法负责写特定类的对象的状态,以使相应的 readObject 方法能存储它。

此方法不必关心写入对象的父类或子类的状态。使用 writeObject 方法或基本类型支持的 DataOutput

方法将每个域的状态保存到 ObjectOutputStream 中。

序列化操作不能输出没有实现 java.io.Serializable 接口的任一对象的域。非序列化对象的子类可以是序列化的。

在这种情况下,非序列化类必须有一个无参构造子,使它的域能被初始化。 在此情况下,子类负责保存和恢复非序列化类的状态。

通常情况父类的域是可存储的(公有的、包或保护的),或存在用于恢复它的状态的可使用的获取或设置方法。

实现抛出 NotSerializableException 异常的 writeObject 和 readObject 方法能阻止一个对象的序列化。

ObjectOutputStream 将获取这个异常,并放弃这个序列化过程。实现外部接口可以使对象完全控制此对象序列化形式的内容和格式。

调用外部接口的方法:writeExternal 和 readExternal 保存和恢复对象状态。当一个类实现了这些方法时,

它们就能使用 ObjectOutput 和 ObjectInput 方法的所有方法写入或读取它们自己的状态。对象负责管理它出现的相应版本。

import java.io.*;

import java.util.*;

public class Logon implements Serializable {

private Date date = new Date();

private String username;

private transient String password;

Logon(String name, String pwd) {

username = name;

password = pwd;

}

public String toString() {

String pwd = (password == null) ? "(n/a)" : password;

return "logon info: \n " + "username: " + username + "\n date: " + date + "\n password: " + pwd;

}

public static void main(String[] args) throws IOException, ClassNotFoundException {

Logon a = new Logon("Morgan", "morgan83");

System.out.println( "logon a = " + a);

ObjectOutputStream o = new ObjectOutputStream( new FileOutputStream("Logon.out"));

o.writeObject(a);

o.close();

int seconds = 5;

long t = System.currentTimeMillis() + seconds * 1000;

while(System.currentTimeMillis() < t) ;

ObjectInputStream in = new ObjectInputStream( new FileInputStream("Logon.out"));

System.out.println( "Recovering object at " + new Date());

a = (Logon)in.readObject();

System.out.println("logon a = " + a);

}

}

类Logon是一个记录登录信息的类,包括用户名和密码。首先它实现了接口Serializable,这就标志着它可以被序列化。

之后再main方法里ObjectOutputStream o = new ObjectOutputStream( new FileOutputStream("Logon.out"));

新建一个对象输出流包装一个文件流,表示对象序列化的目的地是文件Logon.out。然后用方法writeObject开始写入。

想要还原的时候也很简单ObjectInputStream in = new ObjectInputStream( new FileInputStream("Logon.out"));

新建一个对象输入流以文件流Logon.out为参数,之后调用readObject方法就可以了。

java什么情况下传入对象_java中传输对象时候的问题(转)相关推荐

  1. java 类对象_Java中的对象和类是什么?

    今天我们来了解一下在java中到底什么是类,什么是对象,学习之前首先要了解什么是面向过程?什么是面向对象. 计算机语言其实就是和生活中的事件是一样的,每一行代码都代表着一件事情的发展或者结果,是现实世 ...

  2. java判断一个对象是否为空_Java中判断对象是否为空的方法的详解

    首先来看一下工具StringUtils的判断方法: 一种是org.apache.commons.lang3包下的: 另一种是org.springframework.util包下的.这两种StringU ...

  3. java to对象_java中同类对象之间的compareTo()和compare()方法对比分析

    首先我们都知道java中的比较都是同一类对象与对象之间的比较,就好像现实生活中比较人和人的年龄一样,你不会去把人的年龄和人的身高来比较,这显然是没有意义的. java中同类对象之间的比较又分为两种,基 ...

  4. java中的request对象_java中request对象各种方法的使用实例分析

    本文实例讲述了java中request对象各种方法的使用.分享给大家供大家参考,具体如下: request对象是从客户端向服务器端发出请求,包括用户提交的信息以及客户端的一些信息.request对象是 ...

  5. java中file对象_Java中File对象的常用方法

    创建: 1.createNewFile()指定位置创建一个空文件,成功就返回true,如果已存在就不创建,然后返回false. 2.mkdir() 在指定位置创建一个单级文件夹. 3.mkdirs() ...

  6. java 中 class 对象_java中Class对象详解

    java中把生成Class对象和实例对象弄混了,更何况生成Class对象和生成instance都有多种方式.所以只有弄清其中的原理,才可以深入理解.首先要生成Class对象,然后再生成Instance ...

  7. java list 去重 相同的相加_Java 中的数据流和函数式编程 | Linux 中国

    学习如何使用 Java 8 中的流 API 和函数式编程结构.-- Marty Kalin 当 Java SE 8(又名核心 Java 8)在 2014 年被推出时,它引入了一些更改,从根本上影响了用 ...

  8. java 怎么把list流化_Java 中的数据流和函数式编程

    原标题:Java 中的数据流和函数式编程 学习如何使用 Java 8 中的流 API 和函数式编程结构.-- Marty Kalin(作者) 当 Java SE 8(又名核心 Java 8)在 201 ...

  9. java代码中出现黑色画线_从对象流中读取对象,请在画线处加入代码完成此程序【 】。 import java.util.*; import ja...

    从对象流中读取对象,请在画线处加入代码完成此程序[ ]. import java.util.*; import ja 更多相关问题 [问答题,简答题] "三好一满意"是什么? [单 ...

最新文章

  1. 人群密度估计--CSRNet: Dilated Convolutional Neural Networks for Understanding the Highly Congested Scenes
  2. hdu2222(看一些单词哪些在模式串中出现过)
  3. oracle数据泵导出csv文件,数据泵expdp导出遇到ORA-01555和ORA-22924问题的分析和处理...
  4. 服务器磁盘操作系统双机软件集成,实战:ROSE HA双机热备系统安装指南
  5. python的功能名称_ML获取功能选择后的功能名称SelectPercentile,python
  6. linux永久启动服务命令,Linux(CentOS)用service命令启动任意服务
  7. 对makefile中:单冒号普通规则和::双冒号规则的理解 -转
  8. 一个必用的javascript框架:underscore.js - wine的思考 - ITeye技术网站
  9. sketch软件_8款原型设计工具与Sketch的强强组合,轻松构建交互原型
  10. 计算机重装后如何添加打印机,系统重装后,电脑无法连接打印机怎么办?
  11. material-table的使用
  12. 2008年顶尖 Web 设计师访谈
  13. 苹果电脑为什么要换 CPU:Intel 与 ARM 的战争
  14. 学术解读:nmn是不是保健品,nmn最新研究成果
  15. 谁教会老公出轨外面养情人
  16. 5.基于Abp的DDD框架
  17. 烛光晚餐矢量图(编号:82204)_日常生活_矢量人物_矢量素材
  18. docker中部署piggymetrics微服务项目
  19. 平板电脑人气爆棚 上网本遭遇“消亡论”
  20. SLsec题目wp(2)

热门文章

  1. 基于分层卷积神经网络的皮肤镜图像分类方法
  2. 上古卷轴5移除瑟拉娜兜帽_《上古卷轴5》那个令我心疼又感动的角色,大小姐瑟拉娜...
  3. python人工智能项目实例-python人工智能项目实战,PDF+源码
  4. 制作所问数据页面_关于数据可视化页面制作
  5. python描述统计函数_Python Pandas之描述性统计
  6. 苹果手机充电口接触不良怎么办_充电器接触不良怎么办 高手来教你几招-装修攻略...
  7. 2007年西北工业大学计算机专业
  8. css三行代码实现多行文字超出部分省略号代替
  9. DevOps的这些经典著作,你都看过了吗?
  10. 为什么电流PI调节器输出的是电压?为什么转速PI调节器输出的就是电流?(双闭环FOC)