- 话不多说,直接撸图:
1》Eden中通过可达性分析,存活下来的对象直接通过复制算法移动到From区域中,此时该对象的分代年龄加1:
2》当下一次虚拟机进行【Minor GC】时,会同时对【Eden】和【From】进行垃圾回收,如果搞对象还在使用中,则被移动到另一个【From】区,对象分代年龄再次加1:
3》当该对象年龄达到15时,此时它已经是一个老不死的对象了,所以可以移动到老年区:
- 通常什么样的对象会被移动到老年代
1》线程池
2》静态变量引用的对象
3》Spring容器中的Bean,Service,Controller等
4》代码初始化的缓存对象等
- 实践一下,打开【cmd】,输入【jvisualvm】指令,可以打开一个jdk自带的一个内存监控界面:
- 当老年代中空间被占满后,则会触发【Full GC】 ,从而导致【STW】(即Stop the world);通常我们会对JVM进行调优,从而减少Full GC次数,已达到性能提高
- 这里引申一个概念,【对象头】,以下例子为64位JVM下:
- JVM如何调优呢?话不多说,上案例:
- 通常我们会默认设置一个JVM空间分配:
#堆空间 默认3g,最大3g
#元空间 默认512MB,最大512MB
java -Xms3072M -Xms3072 -Xss1M -XX:MetaspaceSize=512M -XX:MetaspaceSize=512M -jar xxx.jar
- 我们从GC角度分析一下,在【Eden】区存满后,此时会触发【minor GC】,改60MB对象(即订单对象)应该从【Eden】区移动到【S1】区域,但是【S1】区域大小仅有50MB,所以实际上会被直接移动到【old区】:
- 此时会出现一个问题,如果【old区】被占满后,就会触发【Full GC】,即JVM会达到【Stop the world】情况,如果【Stop the world】过于频繁(即每13*33秒触发一次),则使得JVM性能急剧下降
那么问题来了,能否对JVM调优,让其几乎不发生【Full GC】?
- 我们可以适当提高新生代内存,降低老年代内存分配:
#堆空间 默认3g,最大3g 新生代2g
#元空间 默认512MB,最大512MB
java -Xms3072M -Xms3072M -Xmn2048M -Xss1M -XX:MetaspaceSize=256M -XX:MetaspaceSize=256M -jar xxx.jar
- 这样在【minor GC】会一同将【Eden】区和【S1】区同时回收,基本不会有对象可以移动至【old】区