關於 java.io.OptionalDataException
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就會導致這種情況
定位問題的辦法:
修改JDK 的library裡的ObjectInputStream類,當出現StreamCorruptedException時把Stream裡的前4K位元組寫到console ouput中。可以通過這個方法找到第一次破壞協議的序列化的內容,以這個序列化的內容作為線索找出應用問題發生的地方。在出現問題的系統上加上這個補丁。這個補丁需要使用-Xbootclasspath來設定,影響JVM boot ClassLoader.