GC是什么?为什么要有GC?
GC(Garbage Collection)是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,垃圾回收的执行速度则影响着整个程序的执行效率,Java语言没有提供释放已分配内存的显示操作方法。 Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉显示的垃圾回收调用。 垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。
垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。 在Java诞生初期,垃圾回收是Java最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今Java的垃圾回收机制已经成为被诟病的东西。移动智能终端用户通常觉得iOS的系统比Android系统有更好的用户体验,其中一个深层次的原因就在于Android系统中垃圾回收的不可预知性。
你知道哪些垃圾回收算法?各自的特点?
GC最基础的算法有三种: 标记 -清除算法、标记-压缩算法和复制算法,我们常用的垃圾回收器一般都采用分代收集算法。
1)标记-清除算法,“标记-清除”(Mark-Sweep)算法,如它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。
2)标记-压缩算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收。
3)复制算法,“复制”(Copying)的收集算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
4)分代收集算法,“分代收集”(Generational Collection)算法,把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。
详细内容请查阅:雨点的名字 https://www.cnblogs.com/qdhxhz/p/9211095.html
JVM 如何判断一个对象是否应该被回收?(JVM 怎么判断对象是无用对象?)
垃圾回收器首先要做的就是,判断一个对象是存活状态还是死亡状态,死亡的对象将会被标识为垃圾数据并等待收集器进行清除。
判断一个对象是否为死亡状态的常用算法有两个:引用计数器算法和可达性分析算法。
(1)引用计数器算法
引用计数算法(Reference Counting) 属于垃圾收集器最早的实现算法了,它是指在创建对象时关联一个与之相对应的counter计数器,当此对象被使用时counter加 1,相反销毁时counter -1。当此计数器为 0 时,则表示此对象未使用,可以被垃圾收集器回收。
优点: 实时性比较高,只要对象计数器为 0,则可以直接进行回收操作。
缺点:无法解决循环引用的问题。
class CustomOne { private CustomTwo two; public CustomTwo getCustomTwo() { return two; } public void setCustomTwo(CustomTwo two) { this.two = two; } } class CustomTwo { private CustomOne one; public CustomOne getCustomOne() { return one; } public void setCustomOne(CustomOne one) { this.one = one; } } public class RefCountingTest { public static void main(String[] args) { CustomOne one = new CustomOne(); CustomTwo two = new CustomTwo(); one.setCustomTwo(two); two.setCustomOne(one); one = null; two = null; } }
即使 one 和 two 都为 null,但因为循环引用的问题,两个对象都不能被垃圾收集器所回收。
(2)可达性分析算法(根搜索算法)
基本思路是通过一系列名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,就证明此对象是不可用的。Java语言是通过根搜索算法(可达性分析算法)来判断对象是否存活的。
其中 5、6、7 与根对象不可达,即为死亡。
注:程序员对垃圾回收机制 只有建议权,没有控制权。
根搜索算法中的根节点可以是哪些对象?
(1). 虚拟机栈(栈帧中的局部变量区,也叫做局部变量表)中引用的对象。
(2). 方法区中的类静态属性引用的对象。
(3). 方法区中常量引用的对象。
(4). 本地方法栈中JNI(Native方法)引用的对象。