Java8以前
java8
public void doRequest() {
MyService myService = new MyService();
myService.doService();
}
1.如果eden区域满了,此时必然触发垃圾回收,young-gc,ygc,谁是可以回收的?没有被引用的对象就要被回收。
垃圾回收的时候有一个概念,叫stop the wordl,停止你的jvm里的工作线程的运行,然后扫描所有的对象,判断那些可以回收,那些不可以回收。
年轻代而言,大部分情况,对象生存周期很短,可能在0.01ms之内,线程执行了3个方法,创建了几个对象,0.01ms之后方法就都执行结束了,此时那几个对象就会在0.01ms变成垃圾可以回收。
1.对于年轻代采用复制算法,如果eden区满了,把eden区内的存活的对象转移到S1区,然后把eden清空。
2.当eden再次满了,又会触发ygc,此时会把eden区的对象和S1区仍然存活的对象转移到S2区,然后把eden和S1区清空。
3.当eden再次满了,又触发young gc,这个时候把S2区的对象和eden区存活的对象复制熬S1区然后再把S2和eden区的对象自清空。
年轻代对象转移到老年代区域,三种情况:
- 第一种场景,有的对象在年轻代熬过了很多次垃圾回收,,此时会认为这个对象是要长期存活的对象。
例如:
Spring 容器中,对每个bean实例对象就一个,长期存活,一直被使用。
@Service
public class MyServiceImpl implements MyService {
}
- 第二种情况,young gc的时候S区放不下的情况,会直接把年轻代对象放到老年代。
- 第三种情况,大对象。
采用标记-整理算法,把老年代存活的对象标记出来,移动到一片内存空间中,剩余的空间都是垃圾对象整个清理掉。
常用垃圾回收器:
-
parnew(年轻代)+cms(老年代)组合(JDK8以及JDK8以前),cms回收分阶段:初始标记,并发标记,并发清理。老年代回收很慢,比年轻代慢10倍以上。
特点:多线程,采用标记-整理算法。
应用场景:注重高吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge+Parallel Old 收集器。
- g1直接分代回收。(JDK9)
见博客
- 内存区域大小,每个线程的栈大小,metaspace大小,堆内存大小,年轻代和老年代大小,eden和suivivor区域的大小分别是多少。
- 垃圾回收器,垃圾回收器设置的参数。