Java是一门自动回收垃圾的的语言,一般来说程序员不需要特别关心垃圾回收。
Jvm的优点:解放了程序员需要大量的代码手动回收。
缺点:可控性较差,有可能造成内存溢出,
说到内存溢出跟内存泄露的话他们俩的区别就是
应用程序在申请内存以后使用完毕无法及时释放申请的内存空间,一次的内存泄露危害可以忽略如果任由其发展的话最终会导致内存溢出,例如读取文件后流要进行及时关闭,数据库的链接及时释放,内存溢出是指应用程序在申请内存时候没有足够的内存空间供其使用
Jvm的垃圾回收分为三步
第一步
确定哪些对象需要回收
在执行确定哪些对象需要回收的时候使用
引用计数法
什么叫引用计数算法,简单来讲就是判断对象的引用数量,给对象共添加一个引用计数器,如果有引用对他进行引用的时候,计数器的值+1,当引用失效,计数器的值-1,如果某个对象的计数器的值是0,表示这个对象没有人对他进行引用,也就意味着是一个失效的垃圾对象,就会被jc回收
但是如果这种简单的算法在当前jvm中并没有被采用, 原因是他并不能解决对象之间互相引用或者循环引用的问题。
可达性分析算法
因为引用计数法的缺点又引入了可达性分析算法,通过判断对象的引用链接是否可达来决定对象是否可以被回收,可达性分析算法是从离散数学中的图引入的,程序把所有引用关系看做一张图,通过一些列名为GC Roots 没有任何引用链相连,也就是GC Roots 到这个对象不可达时,择证明此对象是不可用的。
第二步
什么时候进行回收?
Cpu空闲的时候进行回收
堆内存满的时候进行回收
主动调用system.gc()方法进行尝试回收
第三步
怎么回收?
标记清除法
是最基础的一种算法,分为两个步骤,第一个步骤就是标记,也就是标记处所有需要回收的对象,标记完成后就进行统一的回收掉哪些带有标记的对象。这种算法优点是简单,缺点是效率问题,还有一个最大的缺点是空间问题,标记清除之后会产生大量不连续的内存碎片,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而造成内存空间浪费。
复制清除法
复制将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对其中的一块进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况。只是这种算法的代价是将内存缩小为原来的一半。
标记整理清除法
标记整理算法与标记清除算法很相似,但最显著的区别是:标记清除算法仅对不存活的对象进行处理,剩余存活对象不做任何处理,造成内存碎片;而标记整理算法不仅对不存活对象进行处理清除,还对剩余的存活对象进行整理,重新整理,因此其不会产生内存碎片。
分代收集算法
分代收集算法是一种比较智能的算法,也是现在jvm使用最多的一种算法,他本身其实不是一个新的算法,而是他会在具体的场景自动选择以上三种算法进行垃圾对象回收。
堆内存中
分为
新生代(使用复制算法)因为存活的对象比较少
老年代使用标记清除或者标记整理清除因为存活的对象比较多
永久带(1.8之后叫作元空间)
网友评论