关于GC的学习以及理解
Java中,存储对象的相关信息主要用的是栈与堆。这些都需要占用内存,一旦内存使用超出给定内存,便会报出内存溢出的错误,java中为了减少该错误出现的频率,从而出现了JavaGC处理器。
如何确定一个对象需要回收
在java中一个出现了两种方法,一种是引用计数法,还有一种就是可达性分析
引用计数法
当有一个地方引用了该对象时,该对象的引用计数便+1,引用失效则-1,任何时刻计数器都为0时,则该对象则不背引用。但在引用计数器中,可能会出现循环引用的问题。
可达性分析
根据“GC ROOT”链,对象作为搜索起点,如何对象与“GCROOT”链中没有可达路径,则被标记为不可达对象,但需要被标记两次之后,该对象才会被认为是需要回收的对象,并且进行回收
GC时Java堆的结构
新生代
用于存储一些新建立的对象,在新生代中,还分成了EdenSpace、Survivor From、Survivor To。其中占的内存比分别是8/10,1/10,1/10。
Eden:主要存储新创建的对象
Survivor From:主要存储存活过一次以上的对象
Survivor To:在GC时扫描到存活的对象复制到该区域中。
当一个对象在新生代存活超过十五次以上则会被转移到老年代中。
新生代主要采用MajorGC:
将Eden区和Survivor From区中不能被回收的对象先复制到Survivor To区域中,之后对Eden区和 Survivor From区进行一次清空。之后将From区和To区域进行一次互换。
在新生代中,如果对象过大也会转移到老年代中。
老年代
存放生命周期较长的对象,一般使用标记整理算法,因此会出现较多的内存碎片,当老年代的内存满了的时候,会爆OOM的错误
永久代
在JDK1.7及之前都是使用永久代,现在改成了元空间,在该内存中存放的是Class 和 Meta的信息,该内存不会在主程序运行时进行GC回收,因此会随着Class类信息的增多而报出OOM。