针对GC的简单介绍
JVM对自己的内存进行了划分5个区域,分别是堆,栈,方法区,本地方法栈,程序计数器。Java中对每一种类型都规定了具体的不可变的大小。所以所有的内存都是由JVM自动分配,所有的内存管理和回收都是由JVM自动进行的。
对象的回收是由垃圾收集器(Garbage Collector)执行的。默认堆内存的使用率超过70%的时候,会启动GC。
那么堆内存是如何划分的呢?
在堆内存中划分为新生代(Young Generation)和老生代(Old Generation),新生代中又分为幸存者区(Suevivor)和伊甸园区(Eden),而在幸存者区又划分出了to和from两个区域。
对象创建过程:
出生在Eden区,经过一次扫描——>幸存者区(Suevivor),经过多次扫描——>老生代(Old Generation),经历极少次扫描,频率远远低于新生代。
堆溢出错误:
OutOfMemoryError:Java heap space 堆溢出错误
- 当对象创建后,会在Eden区开辟空间,如果内存不够,会进行第一次初代回收;
- 然后再次尝试Eden区,如果仍未放下会进行第二次初代回收;
- 再尝试Eden区,如果还未放下则会直接尝试放入老生代,如果老生代放不下则进行第一次完全回收;
- 回收后再次尝试放入新生代,如果还未成功则进行第三次初代回收;
- 再次尝试放入新生代,如果放不下则尝试老生代,如果仍放不下则进行第二次完全回收;
- 回收后再次尝试放入新生代,如果放不下则尝试老生代,如果经历了三次初代两次完全仍未放下,则报堆溢出错误。
GC算法
GC算法分别包括标记-清除,标记-整理,复制算法以及分代回收四种(其实是三种)。
标记-清除:将空间里的对象进行扫描,挂掉的进行一个标记,然后对其进行统一回收,缺点是容易造成空间碎片化,当有大对象放入时可能会再次触发垃圾回收机制;
标记-整理:清理的过程和之前一样,只不过在清理后会整体对空间进行整理,将对象再次排列。缺点是效率低;
复制算法:将内存空间一分为二,也就是Suevivor区的from和to两部分,每次只使用一个,当使用的空间触发垃圾回收以后,将所有存活对象复制到另一部分,然后将使用的空间直接全部清除干净。
分代回收:这个一般是说指jvm的GC算法,在新生代使用复制算法,老生代使用标记-整理或标记-清除算法。
总结:
GC是针对于堆内存的一个垃圾回收机制,默认当堆内存使用超过70%后会自动开启,如果对象经历了三次初代两次完全回收都无法放入,则报OutOfMemoryError:Java heap space(堆内存溢出错误)。