天天看點

兩個郁悶的異常: java.lang.StackOverflowError和java.net.SocketException: Broken pipe

debug了幾乎一天,就為了一個bug,折騰死我了。

bug的緣由是因為寫代碼的時候不小心,将:

public boolean isEmpty() {

return this.queue.isEmpty();

}

寫成了:

public boolean isEmpty() {

return this.isEmpty();

}

很明顯,一個函數開始無限制地遞歸地調用自己了。

過不了多久,這個函數所在的thread的stack就會滿了,是以會抛出 StackOverflowError。

一旦發現了java.lang.StackOverflowError,就說明程式中存在着死循環,或者遞歸層次過多,将目前thread所配置設定的stack全部用完了...

在我的程式中,這個java.lang.StackOverflowError是個意料之外的異常,我沒有捕捉它,相反,這個exception被mina拿到了。在mina架構中,一旦它抓住了一個異常,就會調用exceptionCaught方法,這個方法預設會将Session關閉,于是反映出的現象是:

client端如果從connection pool中提取之前用過的socket進行通信,就會報告java.net.SocketException: Broken pipe。

原因就是Server端的socket被server主動關閉了。

這個現象非常類似于linux C網絡程式設計中出現的SIGPIPE信号。雖然我沒有查到準确的資料,但是我大概可以确定java中的Broken pipe異常就是因為檢測到了SIGPIPE。

而産生SIGPIPE的一個典型場景就是在client-server架構中,server端主動關閉了socket連接配接。這時候client端的socket就會接收到一個RST包。如果我們繼續對一個已經接收了RST包的socket調用寫操作,就會産生SIGPIPE了。