那位先生

个人站

前世五百次回眸,才能换得今生的一次擦肩而过。


垃圾收集器和内存分配策略

1.对象已死吗?

1.判断方法

判断一个对象是否死亡的方法:引用计数算法和可达性分析算法。
引用计数算法:给对象添加一个引用计数器,有一个地方引用它就给它+1,引用失效就-1,当值为0表示引用已失效。缺点:无法解决对象之间相互引用的问题。
可达性分析算法:通过一系列的称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有 任何引用链相连时,则证明此对象是不可用的。

1.2 可作为GC Roots的对象

虚拟机栈(栈帧中的本地变量表)中引用的对象。
方法区中类静态属性引用的对象。
方法区中常量引用的对象。
本地方法栈中JNI(即一般说的Native方法)引用的对象。

1.3.关于引用

JDK1.2后引用分为强引用、软引用、弱引用、虚引用。
强引用:例如:A a = new A();,只要强引用存在,垃圾收集器就永远不会回收掉被引用的对象。
软引用:用于描述有用但非必须的对象,它会在内存溢出前被回收。
弱引用:用于描述非必须的对象,它在下一次垃圾收集时被回收。
虚引用:无法通过虚引用取得对象实例。
各状态可达性关系图

1.4.tips

废弃常量的判断:没有任何地方引用该常量。
无用类的判断:1.java堆中不存在该类的任何实例;2.该类的类加载器已被回收;3.该类对应的java.lang.class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。

2.垃圾收集算法

2.1.标记清除算法

过程:首先标记出所有要回收的对象,在标记完成统一回收所有被标记的对象。
缺点:效率不高;标记清除后产生大量不连续的内存碎片。

2.2.复制算法

过程:将可用内存按容量划分为大小相等的两块 ,每次只使用其中的一块。当这一块用完了,将就还存活的对象复制到另一块上面,然后再把已使用过的内存空间一次清理掉。
优点:实现简单、运行高效;
缺点:内存利用率低,将内存的使用缩小一半。

2.3.标记-整理算法

过程:标记过程仍然与“标记-清除”过程一致,但后续步骤不是对可回收对象进行直接清理,而是让所有存活的对象都移动另一端,然后清理掉端边界以外的内存。

2.4.分代收集算法

java堆中分为新生代和老年代。新生代每次垃圾收集都有大量对象死去,存活的少量,因此采用复制算法;老年代对象存活率高,采用标记-清除或标记-整理算法。

3.垃圾收集器

各种垃圾收集器 垃圾收集器 如果两个收集器之间存在连线,说明他们可以搭配使用。jdk1.8后Serial和cms,ParNew和Serial Old不推荐搭配了。
查看系统默认垃圾收集器:cmd命令行执行:java -XX:+PrintCommandLineFlags -version。
jdk1.8默认:-XX:+UseParallelGC(Parallel Scavenge(PSYongGen))。
改成其它串行:-XX:+UseSerialGC。

3.1.Serial

单线程的垃圾收集器,简单高效,对于限定单个CPU环境来说,没有现成交互的开销可以获得高效的垃圾收集效率。 工作时会停掉其它线程。Client模式下默认的新生代收集器。
启用:-XX:+UseSerialGC,启用后老年代默认搭配Serial Old
算法:复制算法。

3.2.Serial Old

Serial的老年代版本,单线程(1.8后不推荐使用)。
算法:标记-整理。

3.3.ParNew

收集器的多线程版本,多个线程同时进行垃圾收集工作,同样在其工作时会停止用户的其它线程。Server模式下虚拟机首选的新声代收集器,除serial外唯一可以与CMS一起工作的新生代垃圾收集器。
启用:-XX:UseParNewGC。(只影响新生代),老年代默认 serial old,但是这个组合不推荐使用。
算法:复制算法。

3.4.Parallel Scavenge(PSYongGen)

并行的多线程垃圾收集器。他与CMS等的区别是,他们关心的尽可能的缩短垃圾收集时用户线程的停顿时间, 而Parallel Scavenge则侧重于达到一个可控制的吞吐量。 (吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间),吞吐量高可以高效率的利用CPU时间)。 有自适应调节策略,可以自动调节吞吐量和停顿时间。
激活:-XX:+UseParallelGC或-XX:+UseParallelOldGC(可互相激活)。
算法:复制算法。

3.5.Parallel Old

Parallel Scavenge的老年代版本,存在目的与Parallel Scavenge一起工作。因为Parallel Scavenge只能和Parallel Old以及Serial Old一起工作。

3.6.CMS

以获取最短停顿时间为目标的垃圾收集器。
工作步骤:初始标记–>并发标记–>重新标记–>并发清除。
初始标记:标记GC–ROOTS能直接关联到的对象;并发标记:进行GC ROOTS tracing的过程。初始标记仍然会停用户线程。
重新标记:修正并发标记期间因用户程序继续运行而导致标记部分发生变动的标记。仍然会停用户线程。
注意:并发标记和并发清除期间可以和用户线程一同工作。
优点:并发收集、低停顿、适合互联网站或者B/S的服务器器上,这类应用尤其重视服务器的响应速度。
缺点:并发执行对CPU资源敏感,收集时会增加堆内存的占用,因此必须在老年代堆内存用尽前完成垃圾回收, 否则将触发担保机制由serial old收集,出现STW造成更大的停顿;无法清理浮动垃圾,收集结束后产生大量空间碎片。
开启:-XX:+UseConcMarkSweepGC,开启后自动将parNewGC打开,同时Serial Old会作为CMS的后备。
算法:标记-清除。

3.7.G1收集器

开启:-XX:+UseG1GC,jdk1.7u4后可用。
region区域化的垃圾收集器,分成一小块一小块,不再明显区分新声代和老年代(但每个region还会分Eden的region,survior,old,humongous的region(超大对象))。 只需按照区域扫描,不需要全内存扫描。可以通过参数指定region大小, 默认分2048个region.
特点:
1.并发和并行:利用多个CPU来缩短停顿时间,通过并发方式在收集垃圾时不用停止其它线程。
2.分代收集:采用不同的方式去处理新创建的对象、已存活一段时间的对象以及熬过多次GC的对象。
3.空间整合:G1从整体看是基于“标记-整理”,从局部看是基于“复制”算法的实现。
4.可预测的停顿:比如说给你A秒的时间内,垃圾收集的时间不得超过B秒;
运行步骤:
1.初始标记:标记GC–ROOTS能直接关联到的对象,并修改ATMS的值。
2.并发标记:采用不同的方式去处理新创建的对象,已存活一段时间的对象和熬过多次GC的对象。
3.最终标记:修正并发标记期间因用户程序继续运行而导致标记部分发生变动的标记。
4.筛选回收:根据回收价值和成本对region排序,并根据用户期望的GC停顿时间制定回收计划;
跟CMS相比优势:空间整合,没有碎片;可预测的停顿。

3.8.如何选择

单CPU或者小内存,单机程序:-XX:UseSerialGC
多CPU,需要最大吞吐量,如后台计算型应用: -XX:+UseParallelGC
多CPU追求低停顿,需要快速响应,如互联网应用:-XX:UseConcMarkSweepGC

3.9.各版本jdk的垃圾收集器

jdk1.7和1.8使用的是Parallel Scavenge和Parallel Old的组合;jdk1.9使用的是G1

3.10测试代码

    public static void main(String[] args) {
        System.out.println("----start----");
        String msg = "hello GC";
        try {
            while (true){
                msg += msg+ new Random().nextInt(88888888)+new Random().nextInt(666666);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        
    }

4.内存分配与回收策略

自动内存管理:给对象分配内存以及回收分配给对象的内存。

4.1.分配策略

1.对象优先在Eden区分配:当Eden区没有足够空间时将触发一次Minor GC。
内存分配比例中:新生代和老年代比例默认1:2,GC日志中显示新生代的大小实际为新生代大小的9/10,因为有一个survior区始终不使用。
java堆的内存分配比例
2.大对象直接进入老年代。大对象:需要大量连续内存空间的java对象。参数标准:-xx:PretenureSizeThreshold,大于这个值的为大对象。一般来说有长字符串和数组。
3.长期存活的对象直接进入老年代。长期存活的对象:经历Minor GC次数:Eden 1次–>Survior n次的对象。n的参数定义:-xx MaxTenuringThreshold,通过这个参数设置。
4.Survior空间中n岁的对象大小总和大于空间的一半,则大于n岁的对象直接进入老年代,即使n小于参数设定的年龄。注:年龄的定义:对象从Eden区进入Survior区后,在Survior区经过一次Minor GC就是一岁。

4.2.空间分配担保

空间分配担保

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
你说多少就多少

比五毛钱特效专业哦