垃圾回收算法:
- 标记清除
- 标记整理
- 复制算法
- 基于上面三种方式衍生的算法:分代垃圾回收算法
标记清除算法:(有垃圾碎片)
标记整理算法:(不会有内存碎片,整理过程中改变了原始对象的地址,导致效率下降)
复制算法:(不会有内存碎片,需要占用双倍内存空间)
三张图解释复制算法:
把内存一分为二,分成from区,to区。需要保留的数据从from区复制到to区。再把from区和to区指向进行交互,使得原来的from区变成to区,to区变成from区。
分代垃圾回收算法:
注意:
- minor gc会引发stop the world 。除了垃圾回收线程外,其它的线程,包括用户线程都会被暂停。为什么要暂停用户线程呢?因为minor gc涉及到复制算法,而复制算法涉及到对象地址的改变,如果用户线程在使用这个对象,但是此时又由于复制算法导致这个对象地址发生改变,可能引发不可预料的错误发生。
- 当对象寿命超过阈值时,会晋升为老年代,最大寿命为15。这个最大寿命并不是固定值,当内存空间紧张时可能也会提前触发机制,并不一定是达到寿命为15时。
- 当老年代空间不足,会先触发minor gc,如果之后空间依然不足,那么会触发full gc,但是full gc的STW的时间会更长。
补充:
1:jdk8和Jdk7的堆空间划分有什么不同?
在Java虚拟机分代垃圾回收机制中,应用程序可用的堆空间可以分为年轻代+老年代+永久代(1.7)/元数据区(1.8)。也就是说在jdk8之前,存在老年代,在jdk8之后把老年代换成了元数据区。
2:永久代为什么会被替代呢?
永久代在使用的时候需要强制指定大小,如果当class太多时会导致永久代内存不足导致永久代内存溢出异常产生。元数据区是可以手动设置内存大小,也可以自动设置内存大小,可以帮助我们很好的解决这个内存溢出问题。
3:Java8中的JVM元空间是不是方法区?
严格来说,不是。首先,方法区是JVM规范的一个概念定义,并不是一个具体的实现,每一个JVM的实现都可以有各自的实现;然后,在Java官方的HotSpot 虚拟机中,Java8版本以后,是用元空间来实现的方法区;在Java8之前的版本,则是用永久代实现的方法区;也就是说,“元空间” 和 “方法区”,一个是HotSpot 的具体实现技术,一个是JVM规范的抽象定义;所以,并不能说“JVM的元空间是方法区”,但是可以说在Java8以后的HotSpot 中“元空间用来实现了方法区”。然后多说一句,这个元空间是使用本地内存(Native Memory)实现的,也就是说它的内存是不在虚拟机内的,所以可以理论上物理机器还有多个内存就可以分配,而不用再受限于JVM本身分配的内存了。