关于 java.io.OptionalDataException
2016-07-15 17:13
573 查看
本文来自:http://jianghuguke.iteye.com/blog/939786
java.io.OptionalDataException
Java的对象传输是在一个keepalive连接上传输的,就是说建立一个网络连接后可以传输很多很多的对象实例。
譬如:A跟B通讯,A端write对象a,write对象b,write对象c;B端就要read对象a,read对象b,read对象c。
但是B端面对的是源源不断的数据,怎么才能区分出a和b的分界点呢,这个就是应用协议要解决的问题了。通用的解决方法是在write a前用一个商定的协议头,在协议头里描述数据的长度,通过这个长度来进行数据的定界。如果在write协议头的时候,序列化的a对象被修改了,那协议头的标识的长度和正式长度就不一致了,这样导致了a对象的部分数据会被read b的时候当作协议头,这样这个连接管道原来有序的数据分界就乱了,只有重置这个连接才能恢复。怎样才能重置这个连接呢,重启是最简单的办法了,重启连接的任何一端都可以。
什么情况下会出现“如果在write协议头的时候,序列化的a对象被修改”的情况呢,在并发环境下,一个线程在进行write对象a,另外一个线程在修改对象a就会导致这种情况。这种情况一般是因为应用使用非线程安全的类,譬如:HashMap,并且应用自身并发控制不严引起的。
定位问题的办法:
修改JDK 的library里的ObjectInputStream类,当出现StreamCorruptedException时把Stream里的前4K字节写到console ouput中。可以通过这个方法找到第一次破坏协议的序列化的内容,以这个序列化的内容作为线索找出应用问题发生的地方。在出现问题的系统上加上这个补丁。这个补丁需要使用-Xbootclasspath来设置,影响JVM boot ClassLoader.
java.io.OptionalDataException
Java的对象传输是在一个keepalive连接上传输的,就是说建立一个网络连接后可以传输很多很多的对象实例。
譬如:A跟B通讯,A端write对象a,write对象b,write对象c;B端就要read对象a,read对象b,read对象c。
但是B端面对的是源源不断的数据,怎么才能区分出a和b的分界点呢,这个就是应用协议要解决的问题了。通用的解决方法是在write a前用一个商定的协议头,在协议头里描述数据的长度,通过这个长度来进行数据的定界。如果在write协议头的时候,序列化的a对象被修改了,那协议头的标识的长度和正式长度就不一致了,这样导致了a对象的部分数据会被read b的时候当作协议头,这样这个连接管道原来有序的数据分界就乱了,只有重置这个连接才能恢复。怎样才能重置这个连接呢,重启是最简单的办法了,重启连接的任何一端都可以。
什么情况下会出现“如果在write协议头的时候,序列化的a对象被修改”的情况呢,在并发环境下,一个线程在进行write对象a,另外一个线程在修改对象a就会导致这种情况。这种情况一般是因为应用使用非线程安全的类,譬如:HashMap,并且应用自身并发控制不严引起的。
定位问题的办法:
修改JDK 的library里的ObjectInputStream类,当出现StreamCorruptedException时把Stream里的前4K字节写到console ouput中。可以通过这个方法找到第一次破坏协议的序列化的内容,以这个序列化的内容作为线索找出应用问题发生的地方。在出现问题的系统上加上这个补丁。这个补丁需要使用-Xbootclasspath来设置,影响JVM boot ClassLoader.
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树