Java垃圾回收详解
Java垃圾回收详解
GC(Garbage Collection)的历史比java还要久远,1960年诞生的Lisp语言当时就在考虑三个问题:
- 哪些内存需要回收
- 什么时候回收
- 如何回收
下面就分别回答这三个疑问,这也是Java面试中常考的知识点
JVM简介
先简单看一下JVM运行时候的内存分布,看起来很复杂,但是一般就简单记成堆(分成新生代和老生代,新生代又分成eden和survivor,后续会讲到)、栈、方法区(当然还有其它,只是为了方便记忆)可以通过一行代码体现出来
Object object = new Object();
在这里,Object object是在栈中, new Object()在堆中申请,而一些类型信息会存储到方法区中。这也对于了下面这个图:
GC三个问题
介绍完上面的基本名词,下面就可以回答GC的三个问题了。
- 哪些内存需要回收
在GC工作流程中,为防止内存的浪费,GC有两种策略来回收内存- PC:程序计数器
引用了对象+1,引用失效-1,虽然简单高效,但是因为不能解决大部分对象之间循环引用的问题,所以大部分JVM没有采用这种方法。 - 可达性分析算法
简单来说,就是自顶向下不断搜索引用,判断对象是否需要回收,具体有:堆,栈,方法区这些。
- PC:程序计数器
- 什么时候回收
大多数情况下,在eden空间不足的情况下,就会触发(eden在上面有),jdk1.6之前策略都不同,这里我们不考虑老版本了。 - 如何回收
新生代和老生代都在堆中。
-新生代GC:大部分java对象创建回收更新快
-老生代GC:长期存在的对象,会进入老生代,所以一般避免大对象(长字符,长数组等。)
内存泄漏和内存溢出
一般在Java内存分配中也有两种情况,叫内存泄漏和内存溢出
- 内存泄漏:是指为一个对象分配内存之后,在对象已经不在使用时未及时的释放,导致一直占据内存单元,使实际可用内存减少,就好像内存泄漏了一样
- 内存溢出:通俗的说就是内存不够用了,比如在一个无限循环中不断创建一个大的对象,很快就会引发内存溢出
小结
主要介绍了GC中的流程和面试常见的三个问题,基本上内存分配和各类名词都介绍到了,具体详细流程可能更复杂,这里不做深入探讨。
我曾七次鄙视自己的灵魂:
第一次,当它本可进取时,却故作谦卑;
第二次,当它在空虚时,用爱欲来填充;
第三次,在困难和容易之间,它选择了容易;
第四次,它犯了错,却借由别人也会犯错来宽慰自己;
第五次,它自由软弱,却把它认为是生命的坚韧;
第六次,当它鄙夷一张丑恶的嘴脸时,却不知那正是自己面具中的一副;
第七次,它侧身于生活的污泥中,虽不甘心,却又畏首畏尾。