由[Ljava.lang.StackTraceElement;@14e77f0發現的一個問題


產品在測試環境部署了好幾天,才發現有一個ERROR:2013-01-23 14:22:33,122 ERROR [com.XXX.XXX.XXX.db.timer.BaseTimer.run] - [Ljava.lang.StackTraceElement;@14e77f0。

在茫茫的日志文件中,這樣一條ERROR實在不是一眼就發現的。要反思下,看來以后要定期在日志中進行搜索,看看有沒有ERROR了。

令我疑惑的是,明明所有的異常,我都是在日志中記錄其堆棧跟蹤的啊,這里怎么就只有一行光禿禿的ERROR呢?

下面是打印出上面那條ERROR的代碼:

catch(Exception ex) {
    logger.error(ex.getStackTrace());
}

參考http://stackoverflow.com/questions/2245088/how-to-display-stack-trace-on-a-caught-exception后發現,error(Throwable ex)只會打印出ex的對象信息,並不會打印完整的堆棧跟蹤。

正確的方法是,調用error(Object, Throwable)方法。如下:

catch(Exception ex) {
    logger.error(ex, ex);
}

 

好,到此可以打印出完整的錯誤日志了。發現了這樣一條異常:java.util.ConcurrentModificationException。

拋異常的代碼如下:

List list = ....
for(Iterator it=list.iterator(); it.hasNext()) {
    Object o = it.next();
    if(...) {
        list.remove(o);
    }   
}

一番研究發現,Iterator 是工作在一個獨立的線程中,並且擁有一個 mutex 鎖。 Iterator 被創建之后會建立一個指向原來對象的單鏈索引表,當原來的對象數量發生變化時,這個索引表的內容不會同步改變,所以當索引指針往后移動的時候就找不到要迭 代的對象,所以按照 fail-fast 原則 Iterator 會馬上拋出 java.util.ConcurrentModificationException 異常。
所以 Iterator 在工作的時候是不允許被迭代的對象被改變的。但你可以使用 Iterator 本身的方法 remove() 來刪除對象, Iterator.remove() 方法會在刪除當前迭代對象的同時維護索引的一致性。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM