手记

JVM系统优化实践(5):什么时候GC以及有哪些GC

您好,我是湘王,这是我的慕课手记,欢迎您来,欢迎您再来~



既然程序运行会产生大量的废弃物也就是垃圾」,那总不能一直堆着不管吧现在就来粗浅地谈谈Java里面什么时候会触发GC以及有哪些GC

通过之前的电商支付系统可以知道系统运行创建的对象都是优先分配在JVM的年轻代中的年轻代里面的对象越来越多快满的时候就会触发垃圾回收机制

这就涉及到一个可达性分析法」,也就是判定哪些对象可以被回收,哪些不能被回收只要某个对象被局部变量引用,就说明该对象有一个GC Roots,此时就不能被回收了

所谓GC Roots在一般情况下指的是方法的局部变量和静态变量只要对象被方法的局部变量、静态变量给引用了,它就不能被回收了至少不能被马上回收

Java对象有几种不同的引用类型:

1、强引用:一个变量显式地引用一个对象;

2、软引用:对一个匿名内部类或者对引用的引用,例如

// 强引用

String str = new String(“abc”);

// 软引用

SoftReference<String> softref = new SoftReference<String>(str);

// 也是软引用

SoftReference<String> softref = new SoftReference<String>(new String(“abc”));

3、弱引用:只具有弱引用的对象拥有更短暂的生命周期,例如

// 弱引用

WeakReference<String> weakref = new WeakReference<String>(new String(“abc”));

str = null;

4、虚引用:顾名思义,就是形同虚设,实际中很少使用,可以不管

 

再来看看有哪些GC方法

年轻代的内存被分为两部分,其中一块创建对象实例,供栈中的局部变量引用。当空间不足时,就可能触发年轻代的垃圾回收



由于一瞬间回收掉大量垃圾对象,可能会造成大量的空白内存区域,大小不一,非常凌乱,造成大量的内存浪费,因此不能直接清除垃圾对象而保留存活对象。所以合理的做法就是复制(复制算法):

1、先保留存活对象;

2、再将存活对象转移(复制)到另一块空白内存中;

3、最后将原区域整体回收;

4、两块区域循环往复着使用。

 

这就是GC当中最最简单最最基础的复制算法

它的缺点:空间使用效率只有50%从图上可以明显看得出来比较浪费空间越大越浪费

优化:年轻代划分为三块

1、1个Eden区:占80%年轻代空间

2、2个Survivor区:S0、S1各占10%年轻代空间

平常情况下可以使用的,就是Eden区和其中一块Survivor区(比如S0)

 

如果Eden区快满了,就会触发Minor GC

1、Minor GC时,Eden中的存活对象会一次性转移到另一块空闲的Survivor区中区(比如S1)

2、Eden区被清空,然后被再次分配新对象

3、如果Eden再满,再次触发Minor GC

4、Eden和S1中的存活对象转移到S0中去

5、如此循环往复

 

对象不可能永远年轻总会慢慢变老自然世界用光阴让人两鬓斑白JVM则默默记住对象的劫数」,并以此决定它的生死

对象每在年轻代“躲过”一次GC而被转移到另一个Survivor时,对象“年龄”就会增加“一岁”(被标记一次),默认是被标记15次之后,就会被转移到老年代,可通过-XX:MaxTenuringThreshold参数设置。

 

当然计算机世界还有自己的规则——除了被标记,还有另一个规则可让对象进入老年代——如果当前Survivor区中,年龄相同的一批对象总大小 ≥ Survivor × 50%,那么这批对象及比它们年龄更大的对象,就都直接进入老年代。例如:如果年龄1 + 年龄2 + 年龄3 ≥ Survivor × 50%,那么大于等于年龄3的所有对象都进入老年代。

 

计算机的规则只有工程师可以干预:通过设置参数XX:PretenureSizeThreshold的值,可以直接将大对象放到老年代,根本不经过年轻代。

工程师就是计算机的上帝



感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~


0人推荐
随时随地看视频
慕课网APP