【发布时间】:2012-09-10 18:51:45
【问题描述】:
我正在尝试在服务器端(Tomcat 6.0.29)序列化 HashMap 并在客户端 android 应用程序上取消实现它。
我第一次尝试这个时遇到了 StreamCorruptedException,但是在我使用干净的 doGet/doPost-Method 创建了一个全新的 servlet 之后,我设法解决了这个问题,不幸的是我得到了一个 EOFException。
所以首先我发布我的代码,然后我将详细解释我的问题:
服务器端代码(这将在 doPost 或 doGet 被调用时执行):
if ("object".equals(request.getParameter("format")))
{
trace.log("Before Serializing");
ObjectOutputStream out = null;
try
{
out = new ObjectOutputStream(response.getOutputStream());
out.writeObject(outerTable);
trace.log("after Serializing");
}
finally
{
if(out != null)
{
try
{
out.flush();
out.close();
}
catch(Exception ex)
{
trace.log("Exception has been thrown "+ex.getMessage());
}
}
}
trace.log("after closing stream");
}
else
{
PrintWriter out = response.getWriter();
out.println(outerTable.toString());
}
outerTable 是在此代码块之前创建的 HashMap,它始终具有正确的值。
在服务器端没有抛出任何错误。 当我尝试使用参数“?format = object”访问我的网络浏览器中的servlet时,我得到 整个序列化字符串。
Android-Application的脚本(该方法在特定按钮被按下后执行http请求):
private synchronized void performNetworkAccess()
{
Runnable run = new Runnable()
{
@Override
public void run()
{
System.out.println("in run()-Method");
ObjectInputStream objInput = null;
try
{
URL url = new URL(myWebsite);
URLConnection con = url.openConnection();
InputStream in = con.getInputStream();
objInput = new ObjectInputStream(in);
outerTable = (HashMap<String, HashMap<String, Object>>) objInput.readObject();
synchronized (monitor)
{
monitor.notifyAll();
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
if (objInput != null)
{
try
{
objInput.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
};
Thread t1 = new Thread(run);
t1.start();
}
调用ObjectInputStream类的构造函数后立即发生异常。
堆栈跟踪:
- W/System.err(1797): java.io.EOFException
- W/System.err(1797):在 libcore.io.Streams.readFully(Streams.java:83)
- W/System.err(1797):在 java.io.DataInputStream.readShort(DataInputStream.java:169)
- W/System.err(1797):在 java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:2102)
- W/System.err(1797):在 java.io.ObjectInputStream.(ObjectInputStream.java:372)
- W/System.err(1797):在 de.tesla.jtheseuscontactsync.ContactSync$4.run(ContactSync.java:602)
- W/System.err(1797):在 java.lang.Thread.run(Thread.java:856)
我已经发现这个问题的出现次数很多,但是我没有看到其中一个在调用 readObject() 之前发生了这个错误。
我已经尝试过的事情:
- 在构造 ObjectOutputStream 后不久添加 out.flush()
- 删除 out.flush() 和/或 out.close() 方法
- 使用 BufferedInput-/-OutputStream 包装 Input-/OutputStream
- 将流作为文件检索并尝试取消实现该文件
奇怪的是,当我第一次通过 FileOutputStream 将对象写入文件并通过 Url.openStream() 从客户端访问该文件(在服务器上)时,ObjectOutputStream 可以完美地读取该对象,不幸的是,这意味着很多当多个用户尝试同时检索此对象时会出现麻烦...
我希望你能帮我解决这个问题:)
【问题讨论】:
-
由 ObjectOutputStream 创建的序列化 Java 对象只能在使用相同实现的环境中反序列化。即使更改 JRE 版本也可以防止反序列化。因此使用序列化来传输复杂的非自写对象结构中的数据是一个非常糟糕的主意。
-
确实我要回答这个问题,但是我看到从文件中完成反序列化是有效的......所以改变了我的帖子:)
-
@Robert 这完全不正确。 Java 序列化机制与所有 JRE 兼容,一直到 Java 1.1。
-
@EJP 机制定义明确,但不属于 JRE 的类。序列化包含 Java API 中从未描述过的私有字段的数据,因此序列化可能会失败,尤其是在使用不同的 Java 运行时环境(例如 Oracle JRE、Android 等)时。无论如何,Java 序列化会创建臃肿的数据并且非常不安全。
标签: java android jakarta-ee