新生代
新生代存放一些新生的对象实例。
新生代内又划分了3个区域,分别是:
- Eden
- SurvivorFrom
- SurvivorTo
一般情况占据的位置是8:1:1
当新生代的Eden区区域不够的时候,就会发生minor GC。
每当进行一次minor GC时,区域间进行数据交换,Eden区和SurvivorFrom区域会把存活的对象放进SurvivorTo区域。
在新生代之中一般采用复制算法进行GC。
老年代
老年代存放比较稳定存活的对象。
对于老年代有Major GC的垃圾回收机制。
有两个触发条件:
- 一个是当新生代发生minor GC之后,仍然不够位置存放新生对象时,借用老年代空间不足时,会发生major GC
- 另一个是当申请一个大的连续空间(如大数组)给较大对象时,也会触发Major GC进行垃圾回收。
永久代
永久代在方法区内,存放Class和Meta的信息。
在GC里面回收永久代的信息有两个
- 一是废弃变量
- 一个是无用的类
废弃变量比较好处理,只要常量池中没有String对象引用,也没有其他对象引用,就会回收。
无用的类的话就有比较多的判断标准。
- 一是Java堆中没有这个类的实例对象
- 二是这个类的类加载器以及被回收
- 三是该类对应的Class对象没有被其他方法引用,不能通过反射访问该类的方法
配合图如下:
元数据
在Java8中完全移除了永久代这个概念,新创建了元数据这个概念。
原本永久代存放的Meta的数据不再存在于方法区内,而是依赖于Native Memory(本地内存)里,而String常量池和类的静态变量转移到Java堆里,因此Java堆内存有所变动。
默认情况下,元数据只受本地内存限制(操作系统的虚拟内存),可以定义新参数MaxMetaspaceSize来限制元数据的大小,如果不限制元空间就会根据需要动态调整。
配合图表示则是: