垃圾回收

2018.5.5 记录学习

  1. 在内存运行的各个部分中,其中程序计数器、虚拟机栈、本地方法栈这三个区域随线程而生,随线程而灭。栈中的栈帧随着方法的进入和退出而执行进栈和出栈

    操作,每个栈帧中分配多少内存基本上在类结构确定下来时就已知的。因此这几个区域的内存分配回收具有确定性。在方法结束和线程结束时,内存自然跟着

    被回收。 

  2. Java 堆和方法区需要内存回收: 一个接口的多个实现类需要的内存不一样,一个方法中的多个分支需要的内存也不一样,我们只有在程序运行期间才知道会创建

    哪些对象。

    方法区: 又称永久代。垃圾回收主要回收两部分内容: 废弃常量和和无用的类。

              1) 已常量池中字面量为例:若字符串abc已经进入常量池,而系统中没有任何String 对象引用该常量,也没有其他地方引用该字面量,

                  那么就认为该字符串可以回收,

              2) 无用的类需要满足3个条件:

                      (1)该类所有的实例都已经被回收,即Java堆中不存在该类的任何实例; 
                      (2)加载该类的ClassLoader已经被回收; 
                      (3)该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

                      是否对类进行回收:-Xnoclassgc 参数控制。

                      

垃圾收集算法(上面确认了什么需要回收,下面讲怎么进行回收):

   各个平台的虚拟机操作内存的方法不同,只介绍几种算法思想 。

      链接1: http://www.cnblogs.com/zhangchenglzhao/p/8922076.html

标记-清除算法

分为标记和清除两步:标记过程参照链接1,在标记完成后统一回收所有被标记的对象。

不足:标记和清除效率都不高; 会产生大量不连续的空间碎片。

复制算法

把内存分为两块,每次只使用其中的一块,当这块满了,就将还存活的对象复制到另一块,然后清空原来的那一块。可以解决内存碎片的问题。

不足:内存只能使用一半。所以通常用于对象存活率较低的情况,如果对象存活率较高,则复制也是要发费时间,效率变低。

通常用于新生代回收: 因为新生代的对象大多数存活事件较短,所以不需要按照1:1 的比例划分 。 而是讲内存分为一块较大的Eden 和两块较小的

survivor空间。每次只用eden和其中一块survivor . 回收时将eden和survivor中还存活的对象一次性的复制到 另一块survivor 上,最后清理掉eden和

刚才使用郭的survivor . Hotspot 默认比例是 8:1:1 。但是可能出现一种情况: 当survivor 放不下还存活的对象,那么就需要老年代做一个分配

担保,所以特别不适合对象存活率较高的空间。

标记整理算法

标记过程和标记清除算法一样。 但是后续不是直接清理可回收对象,而是将所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

适合对象存活率较高的空间,如老年代。

分代收集算法

当前商业虚拟机的垃圾收集都采用 分代收集算法:根据对象存活周期的不同将内存分为几块。一般是将java堆分为新生代和老年代。 根据各自的特点

使用不同的收集算法:新生代存活率低,通常用复制算法。老年代通常用标记整理 或者标记清除。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    

     

  

posted on 2018-05-05 15:19  远方的人  阅读(139)  评论(0编辑  收藏  举报

导航