- Java虚拟机运行时数据区:方法区、堆、虚拟机栈、本地方法栈、程序计数器.
- 对于线程私有的虚拟机栈、本地方法栈、程序计数器内存的回收和分配具有确定性,不需要过多考虑回收的问题;
- 对于方法区和堆,内存的分配和回收都是动态的,这部分才是垃圾收集器关注的重点。
方法区:永久代【回收,废弃常量+无用的类】
堆:新生代+老年代
新生代【98%的对象都是“朝生夕死”,采用复制算法】
老年代【对象存活率较高,采用标记清理或标记整理算法】
新生代:Eden区+Survivor区
比例为8:1(采用复制算法,只浪费了10%的内存空间)
- MinorGC【指发生在新生代的垃圾收集动作,比较频繁】
- MajorGC(FullGC)【指发生在老年代的GC,通常会伴随着一次MinorGC】
5.举个例子
尝试分配3个2MB大小和1个4MB大小的对象
设置Java堆大小为20MB,其中10MB分配给新生代,剩下的10MB分配给老年代
设置新生代Eden区与Survivor区比例为8:1
最后的结果是:Eden区占4MB,Survivor区空闲,老年代被占用6MB
过程:
- 分配时首先会把对象分配到Eden区;
- 当分配了3个2MB的对象之后,Eden区剩余2MB
- 第四个对象分配到Eden区,内存不足,执行一次MinorGC
- 发现存活的3个对象6MB无法转移到Survivor区(1MB)
- 通过分配担保机制,将3个对象6MB提前转移到老年代
- 第四个对象分配到Eden区