JVM技术每周分享整理了JVM技术交流群每周讨论的内容,由群内成员整理归纳而成。如果你有兴趣入群讨论,请关注「Java技术精选」公众号,通过右下角菜单「入群交流」加我好友,获取入群详情。
safePoint是代码的特殊位置.发生GC时,jvm要判断引用关系,引用关系存在OopMap中,不可能每跑一行代码就生成一个OopMap,这会消耗大量的CPU执行时间和内存,所以jvm会在一些特殊的位置生成OopMap,这些位置就是SafePoint.GC时,jvm发出线程中断请求,线程只有跑到SafePoint才会中断,所以SafePoint不能太少.
线程中断主要有两个方式:抢先式中断 线程收到中断请求时,判断在不在safepoint,不在恢复run到safepoint(很少使用) 主动式中断 线程run的时候轮询中断标志,中断标志为真则处于safepoint.
当线程正在run的时候,可以响应jvm的中断请求,跑到SafePoint中断.但是线程处于wait,blocked,sleep状态时,是无法跑到SafePoint中断的.同时这些线程不处于run的状态,引用关系不会发生变化.于是jvm规定了SafeRegion,无论何时发起GC,处于SafeRegion的线程都是安全的可以直接进行GC的.线程离开SafeRegion会检查系统是否已经完成了gc,完成可以离开去run,未完成继续等待可以离开的信号.
CMS (Concurrent Mark Sweep)是一种以获取最短回收停顿时间为目标的Tenured generation收集器.CMS采取的是标记清清除算法.该算法是一定会产生内存碎片的,这是无法避免的.致过多的内存碎片会导致给大对象分配内存时,没有足够大的连续内存而出发full GC. 于是CMS提供了两个参数去解决这个问题:
-XX:UseCMSCompactAtFullCollection默认开启,fullGC时将老年代缩压缩.
-XX:CMSFullGCsBeforeCompaction 则是代表多少次FGC后对老年代做压缩操作,默认值为0,代表每次都压缩, 把对象移动到内存的最左边,可能会影响性能,但是可以消除碎片. 即牺牲一定性能在每次GC之后,将存活的对象整理到一块,消除内存碎片.
问题中有个缺陷,当触发MinorGC时不仅仅是eden区,还会扫描from Survivor 区的内存. ParNew采取的算法是复制清除算法,但是判断对象是否存活仍是可达性算法,采取对对象进行标记判断状态.
全局字符串常量池:本质是一个HashSet,这是一个纯运行时的结构,而且是惰性维护的。注意它只存储String对象的引用,而不存储String对象的内容,根据这个引用可以得到具体的String对象。这个常量池在每个HotSpot VM的实例只有一份,被所有的类共享, JDK6 之前是存放在方法区,JDK7被移到了堆区中.(这里有很多有意思的点课自行百度)