最近一次系统内存泄漏,排查发现是一个框架的清资源的线程异常退出导致的,退出的原因就是抛出了ConcurrentModificationException。
何时抛ConcurrentModificationException?
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.
这个解释其实挺不清楚的,什么叫做没有权限时的修改啊,哪些情况啊。目前所知的是对Collection 遍历时的修改要特别注意。
http://stackoverflow.com/questions/8189466/java-util-concurrentmodificationexception
抛异常代码如下:
1 static 2 { 3 Thread th = new Thread("ShyCacheScanThread"){ 4 public void run() 5 { 6 while( true ) 7 { 8 try{ Thread.sleep(DEFAULT_CHECK_INTERVAL); }catch(InterruptedException e){} 9 synchronized( ALL_CACHE ) 10 { 11 for( AbstractCache cache : ALL_CACHE ) 12 { 13 int x = Math.min(cache.mCapacity/2,cache.mMap.size()-cache.mCapacity); 14 if( x > 0 ) 15 cache.evict(x); 16 } 17 } 18 } 19 } 20 }; 21 th.setDaemon(true); 22 th.start(); 23 }
其中ALL_CACHE是一个List对象,其实这段代码没有什么问题,只是对ALL_CACHE做了遍历,但是这里要特别小心的是,在修改这个对象的其他地方也必须加锁才行,但是不幸的是
1 public AbstractCache(int capacity) 2 { 3 if( capacity <= 0 ) 4 throw new IllegalArgumentException("capacity <= 0"); 5 mCapacity = capacity; 6 mMap = new IntHashMap(capacity); 7 ALL_CACHE.add(this); 8 }
在此处对ALL_CACHE的修改并没有加锁,一旦构造AbstractCache时,ShyCacheScanThread在遍历,那异常就抛出来了。
解决方法就是在add处也加上ALL_CACHE对象的锁,但是并不是很优雅。另我不解的是为啥框架的cache实现要这样子,唉~
问题还没有结束~~
为什么以前没有发生,最近却频频发生?因为上面这段代码只在初始化化的时候运行一次,之后就不会有修改了
时间: 2024-10-12 12:46:26