美文网首页
GC垃圾回收机制

GC垃圾回收机制

作者: 潦倒神仙 | 来源:发表于2018-03-08 22:54 被阅读0次

    1.什么是内存回收机制
    程序计数器、 虚拟机栈、 本地方法栈3个区域随线程而生,随线程而灭;栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。 每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的(尽管在运行期会由JIT编译器进行一些优化,但在本章基于概念模型的讨论中,大体上可以认为是编译期可知的),因此这几个区域的内存分配和回收都具备确定性,在这几个区域内就不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟随着回收了。 而Java堆和方法区则不一样,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样,我们只有在程序处于运行期间时才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,垃圾收集器所关注的是这部分内存。
    垃圾回收机制:寻找java中的对象,分类,寻找出正在使用和不会再使用的对象,然后将不会使用的对象从堆上清除。

    2.怎么判断该对象是没用的对象
    1)标记计数法(引数计数法)
    给内存中的对象打上标记。当对象被引用一次时,计数+1;当引用被释放后,计数-1。当计数为0时,表明该对象能被回收。
    缺点:无法解决对象循环引用的问题。
    什么是循环应用:存在两个对象a和b,a拥有b的引用,b拥有a的引有。

    2)根搜索算法(可达性分析)
    从GC Roots 的对象出发,从这些节点向下搜索,搜索所有的可达对象,这条链路叫引用链。若一个对象不存在于任何一条引用链中,则该对象是不可达的,需要回收。

    在Java语言中,可作为GC Roots的对象包括下面几种:

    虚拟机栈(栈帧中的本地变量表)中引用的对象。
    方法区中类静态属性引用的对象。
    方法区中常量引用的对象。
    本地方法栈中JNI(即一般说的Native方法)引用的对象。
    总结就是,方法运行时,方法中引用的对象;类的静态变量引用的对象;类中常量引用的对象;Native方法中引用的对象。

    3.怎么进行回收
    1)整理。直接进行清空需要被回收的对象。
    问题:内存会被分为一块一块的小碎片,以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
    解决方法:可以将存活的对象整理,使它们变成一个连续的内存。
    i)标记:分别标记处需要回收的对象和不需要回收的对象。
    ii)清除。垃圾收集器清除掉不需要回收的对象。

    缺点:标记对象和压缩内存的过程在JVM中是不高效的,分配的对象越多,垃圾收集的时间就越长。
    iii)压缩。对内存进行压缩操作,将内存分成可用和不可用两大部分。
    2)复制。基本思想是:将内存分为两块a和b,a用来存放对象,b暂不使用。当a存满后,将a上存活的对象复制到b上,此时在b上工作,同时将a清空。而当b满后,重复以上动作。

    内存有新生代,老年代。
    新生代:存放刚产生的对象。分别为Eden,survivor0和survivor1。
    刚产生的对象放在Eden,当该区存满后,将存活的对象复制到survivor0,并且将Eden区数据清空。等下一次垃圾回收时,将eden和该区存活的对象复制到survivor1,清空survivor0和Eden。如此当一定次数后仍未被回收的对象,则将其放入老年代。
    特点:发生在新生代的垃圾收集称为Minor collections。这种收集通常比较快,因为新生代的大部分对象都是需要回收的,那些暂时无法回收的就会被移动到老年代。

    老年代:存放存活时间较长的对象。
    一般,大部分对象会在下一次垃圾回收时被回收掉,只有一小部分对象会保留下来,这部分对象相对稳定,所以老年代的对象回收方法可采用整理的方式。老年代区域的垃圾收集叫做major garbage collection。
    特点:通常Major garbage collection都相对比较慢,因为老年代的收集包括了对所有对象的收集,也就是同时需要收集新生代和老年代的对象。

    上述两者都是Stop the World事件。意味着所有的应用线程都需要停止,直到垃圾回收的操作全部完成。

    垃圾回收是在虚拟机空闲的时候或者内存紧张的时候执行的,什么时候回收不是由程序员来控制的,这也就是java比较耗内存的原因之一。

    垃圾回收时,当检测到对象没有用了,需要被回收的时候并不会马上被回收,而是将其放入到一个准备回收的队列,去执行finalize方法。然等到下次内存回收的时候要是他还是没有被任何人引用的话,就将其给回收了。(如果在finalize方法中重新给对象加个引用,这样对象是有可能不会被回收的)。finalize方法不推荐使用,我们既不能确定什么时候他回被回收,也不能保证这个方法一定会被执行。

    参考:http://blog.csdn.net/q291611265/article/details/45114995
    http://blog.csdn.net/jiafu1115/article/details/7024323
    http://blog.csdn.net/qq496013218/article/details/76968464

    相关文章

      网友评论

          本文标题:GC垃圾回收机制

          本文链接:https://www.haomeiwen.com/subject/kqhefftx.html