c++面试题,c++培训

  

  面试问题:假设我们用一个普通的垃圾收集器,新生代用ParNew,老年用conmarksweep(CMS)。当GC发生的时候,垃圾的对象什么时候会从新生代转移到老年?   

  

  面试问题的常规回答有些面试官可能会回答:新对象是在新生代的伊甸园区分配内存生成的。当Eden区内存容量满了,执行Young GC时,ParNew垃圾收集器会把Eden剩余的存活对象全部复制到其中一个Survivor区,假设是Survivor1区,然后清空Eden区给新对象分配内存。接下来,在Eden区再次满了之后,ParNew会将Eden区和Survivor1区的所有存活对象再次复制到Survivor2区,然后进行清理。这样,存活对象在Survivor1和Survivor2区域内循环往复转移,直到对象的年龄超过15次(每次垃圾回收增加一次年龄),然后存活对象被放入旧年龄。   

  

  另一种情况,大对象超过指定阈值(默认1M),直接放入旧年龄。   

  

  以上两种情况都是经常提到的答案。当实际上还有另外两种我在面试时几乎没听说过的情况时,我们来分析一下剩下的两种情况:   

  

  在年轻的GC之后,太多幸存的物体也进入老年。如果ParNew在Young GC之后发现所有幸存对象都超过了幸存者区域的大小,那么所有幸存对象都会直接转移到old age。   

  

  这涉及到JVM的调优。如果经常发生年轻GC后大量存活对象转移到老年的情况,那么老年也会很快进行老GC。这个过程会很漫长,停世界会发生。用户看起来系统总是一张卡,体验特别差。   

  

  这时候就要考虑增加幸存者区域的大小了。涉及的参数如下:   

  

  -xms 4096m-xmx 4096m-xmn 1024m-xx: survivorratio=8   

  

  解释参数的含义:   

  

  -Xms4096M -Xmx4096M是JVM整个4G堆的最小和最大内存容量。通常,这两个值设置为相同。   

  

  -Xmn1024M表示新一代中可用的内存容量,包括Eden 2幸存者区域。   

  

  -XX3360Survivor Ratio=8表示新生代伊甸园区域的比例,其中伊甸园区域占记忆容量的80%,其余两个幸存者区域各占10%。   

  

  动态年龄判断规则:幸存者区域中所有不在这个GC中的对象都超过了容量的一半。有一种罕见的情况,当它们全部进入老年期时,即当在这个年轻的GC中发现当前幸存者区域中其他剩余幸存对象的内存大小已经超过幸存者区域容量的一半时,ParNew会直接将这些对象全部转移到老年期的堆中。这是因为垃圾收集器认为,如果对象经常需要生存,就应该直接进入老年,作为普通对象使用。   

  

  例如,假设在幸存者区域中,30%的3岁及以上的对象和20%的2岁及以上的对象将被放入老年,1岁的对象将继续移动到另一个幸存者区域。   

  

  再比如,4岁及以上的对象占40%,3岁的对象占10%,那么4岁及以上的对象全部放入老年,2岁及以下的对象继续移动到另一个幸存者区域。   

  

  其实最后这种情况发生的频率最高,新生代对象转移到老年。   

  

  更多的面试题资料,请先关注一下作者,转发一下本文,然后私信发“面试题剖析”给作者,即可获得相关资料,感谢您的阅读。   

相关文章