深入理解java虚拟机之垃圾回收

Aug 13, 2016


  先说点题外话,今天写这篇文章,也算是一次面试总结吧,以前我了解过垃圾回收的基本知识,像引用计数、标记清除、复制算法、标记整理等。还有堆内存划分,新生代、老年代、持久带的概念都有一定了解,不过今天面试的问题彻底把我难住了。

  就不提是哪家了,去面的提前批,看我的本科不是计算机专业,就问了一堆操作系统的”基础”知识,感觉答得不是很好,最后就问到了java的垃圾回收。

  问题是:你是用Java的,java和C++之间有堵墙,这堵墙就是内存空间的回收。Java有垃圾回收机制,那么一旦java内存溢出,应该如何查找错误呢,用过哪些分析工具吗? 还有,你是在XX实习过是吧,你们的QPS大概多少:

  答:大概2000左右。

  接着问:哦,那你应该还不会遇到这个问题,就是当QPS上万以后,可能会由于Java的垃圾回收,导致系统周期性的波动,造成系统很不稳定,为了解决这个问题,在编程的时候应该注意些什么?

  问到这个问题我是一脸懵逼啊,完全没想过,可能面试官也看出来了,也没有提示的意思,开始教育。接着说:这些问题都是基本问题,优秀的程序员不是要遇到了问题才去想如何解决的,你回去可以好好考虑下这些问题。(到这就知道彻底没戏了,后面寒暄几句就走了)

  好了,知道了自己的不足,就找到了努力的方向,看来自己的基础知识确实还不够扎实,平时思考也不够多,这次总结垃圾回收,就当做是一次复习吧。

一、什么是Java垃圾回收?

简单讲,垃圾回收是java对对象生命周期的自动管理。当对象不再有引用时,java垃圾回收器会自动回收对象所占的内存空间。

二、java垃圾回收算法

1、引用计数:实现简单,但是不能解决循环引用。
2、标记清除:老年代算法,存在内存碎片问题。
3、复制算法:新生代算法,当对象存活率不高时才有效率。
4、标记整理:老年代算法。

1、引用计数

利用引用计数算法,当出现循环引用时,无法进行回收。举个例子:

class A{
    public B b = null;
}

class B{
    public A a = null;
}

class Test{
    public static void main(String [] args){
        A a = new A();
        B b = new B();
        a.b = b;
        b.a = a;
        a = null
        b = null;
    }
}

  在main方法中,对象a引用了对象b,对象b也引用了对象a,构成了循环引用。当把a,b设为null时,垃圾回收器将无法回收。

2、标记清除

3、标记整理

4、复制算法