您的位置:首页 > 编程语言 > Java开发

Java的垃圾回收机制

2018-02-26 22:09 197 查看
1 引用计数
        对象每被引用1次,计数器加1,引用每失效1次,计数器减1。任何时刻当计数器为0时,该对象就不能再被引用了,可以回收了。这种方法有个毛病就是会造成循环引用,A对象中引用了B对象,同时B中引用了A对象,其实A对象和B对象都没有再被使用了,都可以被回收了。但由于循环引用,导致计数器都不为0,都不能被回收。

2    引用链(可达性分析)
        在可达性分析中,引入了根节点的概念,所有不能通过引入链到达根节点的对象都可以被回收。其中根节点主要包括四种:方法区中类静态属性引用的对象,方法区中常量引用的对象,虚拟机栈中引用的对象,本地方法栈中JNI(Native方法)引入的对象。

3 方法区的回收
        回收方法区主要是回收没用的常量和类。对于没用的类,必须满足三条:它的实例都被回收了,它的classloader类加载器被回收了,它对应的java.lang.Class没有在任何地方被引用且在任何地方无法通过反射来使用该类的方法。这三个条件是必要不充分条件,即使满足了,该类也不一定就会被回收。
4    堆内存的回收
       标记清除算法,标记所有需要回收的对象,然后统一清除。缺点容易造成内存碎片。标记整理算法,标记所有需要回收的对象,让存活的对象移动到一端,清除掉端边界以外的内存。复制算法,将内存分为两块,一块用完了,将存活的对象复制到另外一块,然后把已使用的那块清理掉。分代收集算法,根据对象存活周期不同,分为新生代和老生代。新生代采用复制算法(复制少量存活对象,大部分对象可以回收),老生代采用标记整理算法(存活率高)。
5    分代收集算法
        分代收集算法是java回收器采用的标准算法,新生代在堆中占1/3,老年代占2/3。其中新生代分为eden, survivor from, survivor to三块,分别占比为8 : 1 : 1。当eden区满了的时候,就会触发minor gc。在gc的过程中,会将eden和survivor from中的存活对象移动到survivor to,然后将eden和survivor from进行清理。如果在清理的过程中,survivor to无法足够来存储某个对象,就会将该对象移动到老年代中。在进行了gc之后,使用的便是eden和survivor to了,下次gc时会将存活对象复制到survivor from,如此反复循环。当对象在survivor区躲过一次gc的话,其对象年龄便会加1,默认情况下,如果对象年龄达到15岁,就会移动到老年代中。有四种情况情况会触发full gc,当系统调用system.gc()时,会建议full gc。当老年代空间不足,方法区空间不足时也会触发full gc。从新生代进入老年代的平均大小大于老年代可用空间,由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小,也会触发full gc。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: