内存申请、对象衰老过程
一、内存申请过程
- JVM会试图为相关Java对象在Eden中初始化一块内存区域;
- 当Eden空间足够时,内存申请结束。否则到下一步;
- JVM试图释放在Eden中所有不活跃的对象(minor collection),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区;
- Survivor区被用来作为Eden及old的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区;
- 当old区空间不够时,JVM会在old区进行major collection;
- 完全垃圾收集后,若Survivor及old区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”Out of memory错误”;
基本的收集算法
复制算法
标记清除算法
标记整理算法
分代算法
什么叫根对象?
- q
q
复制算法
将堆内分成两个相同空间,从根(ThreadLocal的对象,静态对象)开始访问每一个关联的活跃对象,将空间A的活跃对象全部复制到空间B,然后一次性回收整个空间A。 因为只访问活跃对象,将所有活动对象复制走之后就清空整个空间,不用去访问死对象,所以遍历空间的成本较小,但需要巨大的复制成本和较多的内存。
优点:只访问活跃对象,遍历快
缺点:需要内存比较多,浪费一部分内存,不适合年老代
有哪些阶段使用了复制算法?
Serial收集器-XX:+UseSerialGC
ParNew收集器-XX:+UseParNewGC
Parallel Scavenge收集器-XX:+UseParallelGC
标记清除算法
收集器先从根开始访问所有活跃对象,标记为活跃对象。然后再遍历一次整个内存区域,把所有没有标记活跃的对象进行回收处理。该算法遍历整个空间的成本较大暂停时间随空间大小线性增大,而且整理后堆里的碎片很多。
优点:不浪费内存
缺点:遍历2次,2次标记效率都不高,内存碎片多
有哪些阶段使用了标记清除算法?
CMS(Concurrent Mark Sweep)收集器XX:+UseconcMarkSweepGC 标记,置换 不压缩
标记整理算法
综合了上述两者的做法和优点,先标记活跃对象,然后将其合并成较大的内存块。
移动了活跃对象,回收后留下完整内存块。有哪些阶段使用了标记整理算法?
- Serial Old收集器-XX:+UseSerialOldGC
arallel Old收集器-XX:+UseParallelOldGC
分代收集算法
现在比较常用的是分代收集(generational collection,也是SUN VM使用的,J2SE1.2之后引入),即将内存分为几个区域,将不同生命周期的对象放在不同区域里:young generation,tenured generation和permanet generation。绝大部分的objec被分配在young generation(生命周期短),并且大部分的object在这里die。当young generation满了之后,将引发minor collection(YGC)。在minor collection后存活的object会被移动到tenured generation(生命周期比较长)。最后,tenured generation满之后触发major collection。major collection(Full gc)会触发整个heap的回收,包括回收young generation。permanet generation区域比较稳定,主要存放classloader信息
复制算法:young generation有eden、2个survivor 区域组成。其中一个survivor区域一直是空的,是eden区域和另一个survivor区域在下一次copy collection后活着的objecy的目的地。object在survivo区域被复制直到转移到tenured区。
垃圾收集器
Serial收集器-XX:+UseSerialGC 复制收集算法
单线程收集器,收集时会暂停所有工作线程(我们将这件事情称之为Stop The World,下称STW),使用复制收集算法,虚拟机运行在Client模式时的默认新生代收集器。
ParNew收集器-XX:+UseParNewGC 复制收集算法 多线程执行
ParNew收集器就是Serial的多线程版本,除了使用多条收集线程外,其余行为包括算法、STW、对象分配规则、回收策略等都与Serial收集器一摸一样。对应的这种收集器是虚拟机运行在Server模式的默认新生代收集器,在单CPU的环境中,ParNew收集器并不会比Serial收集器有更好的效果。
Parallel Scavenge收集器-XX:+UseParallelGC 复制算法,吞吐量最大化
Parallel Scavenge收集器(下称PS收集器)也是一个多线程收集器,也是使用复制算法,但它的对象分配规则与回收策略都与ParNew收集器有所不同,它是以吞吐量最大化(即GC时间占总运行时间最小)为目标的收集器实现,它允许较长时间的STW换取总吞吐量最大化。
Serial Old收集器-XX:+UseSerialOldGC 标记整理算法
Serial Old是单线程收集器,使用标记-整理算法,是老年代的收集器,上面三种都是使用在新生代收集器。
Parallel Old收集器-XX:+UseParallelOldGC 标记整理算法多线程执行
老年代版本吞吐量优先收集器,使用多线程和标记-整理算法,JVM 1.6提供,在此之前,新生代使用了PS收集器的话,老年代除Serial Old外别无选择,因为PS无法与CMS收集器配合工作。
CMS(Concurrent Mark Sweep)收集器XX:+UseconcMarkSweepGC 标记,置换 不压缩 算法
压缩需要加参数-XX:CMSFullGCsBeforeCompaction(多少次FullGC后压缩内存) 或者-XX+UseCMSCompactAtFullCollection(CMS后压缩内存)
CMS收集器使用的是标记-清除算法,也就是说它在运行期间会产生空间碎片,所以虚拟机提供了参数开启CMS收集结束后再进行一次内存压缩。
CMS垃圾收集器的回收过程: