在Java中JVM的堆内存分两部分: Permanent Space 和 Heap Space。
• Permanent Space 即持久代(Permanent Generation),主要存放JAVA类定义信息,与垃圾收集器要收集的JAVA对象关系不大。
• Heap 分为 Old 和New(Eden ,from,to)即年老代和年轻代,和垃圾回收都有关系。
年轻代
• 存放所有新生成对象。
• 尽可能收集掉生命周期短的对象。
• 分为 Eden 和 Survivor区 (from和to)
• 详解:
- 大部分对象在Eden中生成。当Eden区满时,还存活的对象被复制到Survivor区中(二选一),当一个Survivor区满时,此区的存活对象被复制到另一个Survivor区中,另一个也满时,从前一个Survivor区复制过来的存活对象将可能被复制到年老代。
- 2个Survivor区是对称的,没有先后关系,所以同一个Survivor区中的对象可能来自Eden或Survivor。
- Survivor区至少一个是空的。
- 特殊情况下,根据程序需要可配置多个Survivor。增加了对象在年轻代的存在时间,减少被放到年老代的可能。
- 针对年轻代的垃圾回收即 Young GC。
年老代
• 在年轻代中经历了N次(可配置)垃圾回收后还活着的对象,会被复制到年老代。
• 年老代的垃圾回收即 Full GC
持久代
• 用于存放静态类型数据,比如JAVA Class ,Method 等。持久代对垃圾回收没有显著影响。但是有些应用可能动态生成或调用一些Class,例如Hibernate CGlib等,在这种时候往往需要设置一个比较大的持久代空间来存放这些运行过程中动态增加的类型。
当创建对象时内存申请过程:
- JVM会试图为相关Java对象在年轻代中的Eden区中初始化一块内存区域。
- 当Eden区空间足够时,申请内存结束。否则,下一步
- JVM试图释放Eden区中不活跃的对象(Young GC)。释放后若Eden区中仍然不足放入新对象,JVM则试图将部分Eden区中活跃对象放入Survivor区
- Survivor区作为Eden区和年老代的交换区域,当年老代空间足够时,Survivor区中存活了一定次数的对象会被移到年老代。
- 当年老代空间不够时,JVM会在年老代进行完全的垃圾回收(Full GC)。
- Full GC后,若Survivor以及年老代仍然无法存放从Eden中复制过来的对象,则会导致JVM无法在Eden区为新生成的对象是申请内存,即出现“Out Of Memory”。