垃圾回收是java中的一个大知识点,也是一个著名知识点,毕竟java号称自己先进性的时候总是会带上垃圾回收。于是,它也成了面试中的常客,面试官动不动的就要你解释下什么是垃圾回收,以及它的原理是什么。当然,虽然,以及肯定,那个问你垃圾回收的面试官他99%也只是略知皮毛而已。当面试官问你什么是垃圾回收机制的时候,你应该这样一本正经的反问:请问您问的哪个vm中的垃圾回收机制?
由于垃圾回收中涉及到的概念复杂,算法复杂,你若想弄明白其中的全部细节,必定得不偿失。但是,如果我们掌握了以下的垃圾回收机制的概要,相信在绝大部分的面试中你不会失分。
一:什么是垃圾?
举例来说,一个对象你不用了,它就是垃圾,比如:
public void test01(){
user user = new user();
//...
}
test01方法执行完毕,user对象没有任何用处了,那它就是垃圾了。
二:为什么要进行垃圾回收?
我们知道,对象是存放在堆上的,那么堆有多大?虽然可以通过命令参数进行调整,但是通常情况下,32位系统下,java堆大小设置在2 gb其中,500 mb 分配给新生代(younggen)1.5 gb的分配给老年代(oldgen)空间。即便64位,想想我们pc的硬件内存能有多大。
所以,没用的垃圾,统统回收,让出内存空间,给其它对象用。
三:jdk默认的hotspot vm垃圾回收的机制
1:堆内存的分类
要理解这个机制,首先得明白堆的分类。是的,我们光知道对象存在于堆上,但是不知道堆内部也分为几个空间,如下图所示:
young/new generation 新生代
其内部又分为eden 与两个survivor space 组成。新建的对象都将分配到新生代中,
old/tenured generation 老年代
老年代用于存放程序中经过几次垃圾回收后还存活的对象
(ps:permanent generation 非堆内存,用于存放静态文件,如java类、方法等。持久代对垃圾回收没有显著影响。)
2:回收次序
每个空间的执行顺序如下:
绝大多数刚刚被创建的对象会存放在伊甸园空间。
在伊甸园空间执行了第一次gc之后,存活的对象被移动到其中一个幸存者空间。
此后,在伊甸园空间执行gc之后,存活的对象会被堆积在同一个幸存者空间。
当一个幸存者空间饱和,还在存活的对象会被移动到另一个幸存者空间。之后会清空已经饱和的那个幸存者空间。
在以上的步骤中重复几次依然存活的对象,就会被移动到老年代。
四:垃圾收集器与回收算法
两种类型的代都有自己的收集器,每种收集器采用不同的算法。请记住,对于初级选手,我们并不需要掌握每个算法原理。
新生代收集器使用的收集器:serial、pranew、parallel scavenge
老年代收集器使用的收集器:serial old、parallel old、cms
其对应的算法如下,
serial收集器(复制算法)
新生代单线程收集器,标记和清理都是单线程,优点是简单高效。
serial old收集器(标记-整理算法)
老年代单线程收集器,serial收集器的老年代版本。
parnew收集器(停止-复制算法)
新生代收集器,可以认为是serial收集器的多线程版本,在多核cpu环境下有着比serial更好的表现。
parallel scavenge收集器(停止-复制算法)
并行收集器,追求高吞吐量,高效利用cpu。吞吐量一般为99%, 吞吐量= 用户线程时间/(用户线程时间+gc线程时间)。适合后台应用等对交互相应要求不高的场景。
parallel old收集器(停止-复制算法)
parallel scavenge收集器的老年代版本,并行收集器,吞吐量优先
cms(concurrent mark sweep)收集器(标记-清理算法)
高并发、低停顿,追求最短gc回收停顿时间,cpu占用比较高,响应时间快,停顿时间短,多核cpu 追求高响应时间的选择
五:什么时候会运行垃圾回收?
垃圾回收有两种类型,scavenge gc和full gc。
当新对象生成,并且在eden申请空间失败时,就会触发scavenge gc。此时会对新生代进行垃圾回收。
当,年老代(tenured)被写满、持久代(perm)被写满、system.gc()被显示调用、上一次gc之后heap的各域分配策略动态变化,执行full gc。
注意,无论是那种回收,并不意味着会把全部的垃圾回收掉,而是根据算法自己的判断,在一段时间内除掉一定数量的垃圾,这个时间和数量我们不可知。
以上,就是你必须知道的垃圾回收机制。
以上就是java垃圾回收机制的详细内容。