阅读 深入理解JVM虚拟机笔记二

GC垃圾回收章节:

        1.如何判断对象已死?

            一种说法是引用计数法,当这个对象在其他地方存在引用,就给计数器+1,一旦计数器为0,即表示对象死了。这种方式固然有效 ,但是有一些问题。考虑A持有了B的引用,B持有了A的引用,这种情况下,虽然AB都已经没有用了,但他们都还活着。

            java的GC系统采用可达性分析算法解决这个问题。用图论的语言表述:如果GC Root到这个对象之间是不可达的,那么这个对象就已经死了。可以作为GC Root的对象有:

                    虚拟机栈(栈帧中的本地变量表)中引用的对象;

                    方法区中类静态属性引用的对象;

                    方法区中常量引用的对象;

                    本地方法中native方法引用的对象。

                            ——说的更通俗一点,栈中的引用对象


        2.引用:java中提供了四种引用类型:强引用、软引用、弱引用和虚引用。(详见编程思想)


        3.谈谈回收:

            一个对象,在失去引用到被GC回收,还有两次标记的过程:

            失去引用-->被标记-->是否有finallize()方法,有且该方法未被执行过,则将对象加入F-Queue队列等待执行finallize()方法,否则再次被标记-->执行finallize()方法,最后拯救自己的机会,如果仍旧没有被引用,被标记-->两次标记则再下一次GC运作时回收。


        4.方法区的回收:

            回收常量和堆上回收对象实例类似。

            回收类则比较复杂:需要类所有的实例都已经被回收、加载类的ClassLoader被回收、任何地方都没有使用该类的Class对象,无通过反射获取该类信息时,该类可以被回收。


        5.垃圾回收算法:

            1).标记-回收算法:最基本的算法,缺点是,标记回收会产生大量不连续的空间,当需要开辟一块连续的较大的对象时,可能会不得不提前进入下次回收。

            2).复制-回收算法:将内存一分为二,回收时将仍有用的对象复制到另一块内存,清理掉原内存所有东西。简单高效,但是代价太高。不过对于新生代的垃圾回收(由于新生代对象98%都是 朝生夕死的),可以提供Eden和两块Surviver内存区域(8:1)大小,每次使用一块Surviver和Eden,回收后放入另一个Surviver并清空之前的两块。这样浪费只有10%,可以接受。如果遇到了不可避免的需要空间的时候,老年代区域将会被占用。

            3).标记-整理算法:本质与标记回收差不多,只是会将不需要回收的对象移到内存的一段,然后清除边界外对象,这种方式更适合老年代。

            4).分代算法:对新生代和老年代采取不同的策略,已达到最好的效果。


        6.HotSpot的算法:

            1)枚举根节点:根据我们对引用的规定,搜索GCRoots是一个十分耗时的事情(GC必须停止其他线程,达到一致性),这个过程被称为枚举根节点。

            2)HotSpot采用在安全点(每个线程都将轮训在此处等待GC操作完成)以及安全区域下记录对象的引用信息至OopMap,以便快速枚举根节点。


        7.垃圾收集器:

            1)serial系列:单线程,简单高效,十分适用Client程序,缺点是在并行处理的情况下效率不高,停顿时间过长,体验很差。

            2)ParNew系列:多线程,使用CMS时唯一的并发收集器选择,缺点是在单核情况下效率不一定有serial高。

            3)Parallel Scavenge系列:重视吞吐量,停顿时间的减少不代表性能的优秀,频繁的gc导致停顿总时间提升。而注重吞吐量可以更快的完成工作。

            4)CMS:停顿时间极短,支持并发下的操作。缺点:对CPU资源敏感,无法处理浮动垃圾,标记-清除带来的full gc。

            5)G1:新世代收集器,不稳定,但是性能比CMS优秀。


        8.minor gc:新生代触发的垃圾回收。

            full gc:老年代、方法区触发的垃圾回收。


        9.内存分配:

        大对象(一般如数组)直接去老年代,占用空间过大的也如此。其他的情况, 优先进入新生代,如果新生代空间不足,发起一次minor gc,采取分配担保将一部分新生代对象移至老年代,如果此时老年代空间阈值,将会发生full gc。

        值得一提的是,每活过一次minor gc,对象就会大一岁,超过一定年龄将会被分配到老年代。

猜你喜欢

转载自blog.csdn.net/zkANewer/article/details/79758407