java - 网络 ObjectOutputStream 中的奇数 ArrayIndexOutOfBoundsException
问题描述
我有一个不断向服务器发送消息的客户端。最终我得到了一个我无法理解的ArrayIndexOutOfBoundsException
内部:writeObject
Exception in thread "Core" java.lang.ArrayIndexOutOfBoundsException: Index 256 out of bounds for length 256
at java.base/java.io.ObjectOutputStream$BlockDataOutputStream.writeBytes(ObjectOutputStream.java:1996)
at java.base/java.io.ObjectOutputStream$BlockDataOutputStream.writeUTF(ObjectOutputStream.java:2174)
at java.base/java.io.ObjectOutputStream.writeString(ObjectOutputStream.java:1307)
at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1173)
at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
at ws.hikari.md5.ui.network.Client.sendStatusMessage(Client.java:64)
at ws.hikari.md5.Core.run(Core.java:96)
at java.base/java.lang.Thread.run(Thread.java:834)
在这里ws.hikari.md5.ui.network.Client.sendStatusMessage()
,它被Core调用以将消息发送到服务器。
public class Client implements Runnable {
// ...
protected ObjectOutputStream oos = null;
public boolean connect(){
try{
socket = new Socket(
// host IP,
// host port
);
oos = new ObjectOutputStream(socket.getOutputStream());
}catch(IOException ex){
logger.log(Level.FINER,"Client connect failed",ex);
return false;
}
return true;
}
protected boolean sendStatusMessage(Message msg){
if(null==socket || null==oos){
connect();
return false;
}
GsonBuilder builder = new GsonBuilder();
builder.setPrettyPrinting().serializeNulls();
Gson gson = builder.create();
String serializedMsg = gson.toJson(msg);
try{
oos.writeObject(serializedMsg); // line 64
}catch(SocketException ex){
// just silence it, it's ok if Remote GUI server is offline
connect();
return false;
}catch(IOException ex){
logger.throwing("Client", "sendStatusMessage", ex);
connect();
return false;
}
return true;
}
// ...
}
解决方案
您同时ObjectOutputStream
从多个线程写入相同的内容。这是不支持的。
来源: 来源的一小部分java.io.ObjectOutputStream
:
int n = Math.min(csize - cpos, MAX_BLOCK_SIZE - pos);
int stop = pos + n;
while (pos < stop) {
buf[pos++] = (byte) cbuf[cpos++];
}
其中pos
是与 OOS 关联的 BlockDataOutputStream 实例的字段;各种写入方法会影响它,如果在这两行之间对其进行修改,cbuf
(硬编码为 256 大, vs buf
,硬编码为 1024,因此发生的错误是因为cpos
是 256,因此cbuf[cpos++]
是导致 AIOOBEx 的行,not buf[pos++]
,这是因为stop
太大,这是因为在第 1 行 ( ) 和第 2 行pos
之间进行了修改。int n =...
您无法更改 ObjectOutputStream 的来源,无论如何,这种“崩溃”不是它的错,它的规范,像大多数 OutputStreams 一样,很清楚尝试从多个线程写入它们会导致完全混乱。
推荐阅读
- javascript - 在滚动时向正文添加/删除类
- c++ - C++ 切换语句
- powerquery - powerquery,从分隔列表的分隔列表创建表,包含分隔键值对
- javascript - 根据选择的下拉选项在 DIV 中显示信息
- html - 网站按钮下划线不会消失,我该如何解决?
- hpc - 如何更改 condor 中的设置,以便用户不必更改他们的实验脚本?
- ruby-on-rails - 如何更新嵌套表单 - Ruby on Rails
- python - 创建条纹虚拟卡时如何更改品牌?
- python - 是否有 Tweety python 函数可以将长推文分成线程?
- r - 将单列 Dataframe 转换为 XTS 正在丢失列名