1.数组动态扩容
现象:系统一直在做cms gc,但是老生代一直不降下去,但是执行一次jmap -histo:live
之后,也就是主动触发一次full gc之后,通过jstat -gcutil
来看老生代一下就降下去了.
原因:跨代引用。
ArrayList里的数组扩容,使用的是System.arrayCopy
调用,这是一个native方法,在java层面创建一个新的长度的数组,然后将老数组和新数组都传进去,在native里将老数组里的元素指针拷贝到新数组里,其实做的是浅拷贝。
传给System.arrayCopy
的新数组是在java层面构建传进来的,在新生代分配的可能性最大,这样再加上拷贝仅仅是浅拷贝,那么老生代里的byte数组因为存在新生代里新书组的引用,那仅仅做CMS GC就不可能回收这些老生代的对象了,因为CMS GC的一个gc root就是新生代里的对象。
解决:cms gc回收old之前做一次ygc
-XX:+CMSScavengeBeforeRemark
参考:又抓了一个导致频繁GC的鬼--数组动态扩容