1.原因
JVM在程序运行过程当中,会创建大量的对象,这些对象,大部分是短周期的对象,小部分是长周期的对象,对于短周期的对象,需要频繁地进行垃圾回收以保证无用对象尽早被释放掉,对于长周期对象,则不需要频率垃圾回收以确保无谓地垃圾扫描检测。为解决这种矛盾,Sun JVM的内存管理采用分代的策略。
2.新生代、老年代与持久代
2.1 年轻代 (Young Gen)
新生代主要用于存放新创建的对象,内存大小相对会比较小,垃圾回收会比较频繁。
新生代被分为1个Eden和两个Survivor (From Survior 和 To Survivor),当对象在堆创建时,会进入Eden,垃圾收集器进行回收时会扫描Eden和From Survivor,如果对象仍然存活,则复制到To Survivor ,如果To Survivor已满,则复制到
Old Gen(老年代)。同时,在垃圾收集器几次扫描Survivor空间发现对象仍然存活,则认为该对象应该被持久化,将其移动到Old Gen(老年代)。扫描完毕后jvm会将Eden和From Survivor清空,然后交换两个Survivor(即原来的From Survivor变为
To Survivor ,原来的To Survivor 变为 From Survivor),这样做的目的是减少内存碎片的产生。
我们可以总结出:新生代进行垃圾回收时,采用标记-复制算法避免产生内存碎片,采用空间换时间的方式来加速内存中不被使用的对象回收。
2.2 老年代
老年代主要用来存放jvm认为生命周期比较长的对象(经过几次新生代垃圾收集还存活的对象),内存大小相对比较大,同时垃圾回收也没有那么频繁。老年代主要采用压缩的方式来避免内存碎片(将存活的对象移动到内存的一边)。
2.3 持久代
持久代主要存放类定义、字节码和常量等很少会变更的信息。
若垃圾收集器依据这种小幅度的调整收集不能腾出足够的空间,就会运行Full GC,此时JVM GC停止所有在堆中运行的线程并执行清除动作。