JAVA内存回收算法,主要采用的方式有两种,一种是标记计数器方式,一种是根目录搜索法。
标记计数器方式,是对每一个对象如果被引用,则标记计数器加1,解除引用,则标记计数器减1。当一个对象标记计数器为0时,则回收此对象。但这种方式存在问题,假如两个对象存在交叉引用,则对象值为null时,则无法回收此对象。
而采用根目录搜索法,是从一个根目录对象开始搜索,如果某个对象不可达,则此对象可以回收。
JAVA回收的时候,采用的算法有两种,一种是标记-清除,一种是复制算法。
标记-清除算法:首先在内存中将需要清除的对象标记出来,然后一次性的将对象释放掉。但这种方法存在的问题是,有可能会导致释放的内存不连续,会导致如果申请需要较大连续的内存时,没有足够的内存。
复制算法:会将内存分为平均的两部分,一部分用来使用,另一部分则不使用。当内存不够时,会将使用的那部分内存标记出来,然后将存活的对象复制到另一部分上。之后将使用的内存清空。(但此种算法会导致浪费大量的内存,内存使用量缩小为原来的一半)
常用的方式是结合以上两种来使用。每次使用将内存分为一块较大的Eden和两块survivor区域,每次使用Eden和其中的一块survivor。当需要清除时,将Eden和其中一块survivor的标记的数据复制到另一块survivor中,最后再清理掉Eden和survivor中的数据。
引用强度:强引用->软引用->弱引用->虚引用
JAVA内存区主要分三个区。年轻代,年老代,持久代。
年轻代分3个区,Eden,Survivor0,Survivor1。当经过无数次的minor gc后,仍然存活下来的对象,则进入年老代。在年老代中,对内存的清理为full gc。持久代主要为存放一些静态文件,类信息,classLoader信息等。垃圾回收对持久代没有显著的影响。
JAVA垃圾回收器主要有CMS,JDK1.8新增了个G1垃圾回收器。