最近項目在生產環境拋錯:
at org.hibernate.impl.SessionFactoryImpl.get(SessionFactoryImpl.java:339)
at org.hibernate.impl.SessionFactoryImpl.getQuery(SessionFactoryImpl.java:411)
at org.hibernate.impl.SessionImpl.getQueries(SessionImpl.java:884)
at org.hibernate.impl.SessionImpl.iterate(SessionImpl.java:920)
at org.hibernate.impl.QueryImpl.iterate(QueryImpl.java:41)
....
上述是調用Hibernate查詢資料query.iterate();後,就拋錯了,根據日誌分析,錯誤記錄檔記錄的一般是java.lang.ArrayIndexOutOfBoundsException: -68,後面是一個-128範圍內的負數,並且根據時間逐漸增大,比如到java.lang.ArrayIndexOutOfBoundsException: -2,然後java.lang.ArrayIndexOutOfBoundsException: -1,然後又輪迴到java.lang.ArrayIndexOutOfBoundsException: -127。
開始看了半天一直在找自己代碼的問題,最後通過查看hibernate源碼SessionFactoryImpl.java的339附近代碼,方法如下:
private synchronized Object get(Object key)
{
Object result = this.softQueryCache.get(key);
if (result != null) {
this.strongRefs[(++this.strongRefIndex % 128)] = result;
}
return result;
}
this.strongRefs[(++this.strongRefIndex % 128)] = result;為第339行,strongRefs數組是初始化長度為128的數組,strongRefIndex被定義為:private transient int strongRefIndex = 0;
strongRefIndex是根據每次擷取資料都遞增1的,根據報錯內容,應該是strongRefIndex為負數了,而且每次也確實在遞增。
通過上述分析,strongRefIndex欄位要不記憶體中被無故修改了,或者就是遞增到int的最大長度2147483647了,導致變為了負數。好像沒有其他辦法,只能重啟網站,重啟後問題果然解決了!