堆用于存储对象实例及数组值,可以认为Java中所有通过new创建的对象的内存都在此分配,Heap中对象所占用的内存由GC进行回收。为了让内存回收更加高效,Sun JDK从1.2开始对堆采用了分代管理的方式。

  1. 新生代(New Generation)

大多数情况下Java程序中新建的对象都从新生代分配内存,新生代由Eden Space和两块相同大小的Survivor Space(通常又称为S0和S1或From和To)构成,可通过-Xmn参数来指定新生代的大小,也可通过-XX:SurvivorRatio来调整Eden Space及Survivor Space的大小。不同的GC方式会以不同的方式按此值来划分Eden Space和Survivor Space,有些GC方式还会根据运行状况来动态调整Eden、S0、S1的大小。
2. 老年代(Old Generation或Tenuring Generation)

用于存放新生代中经过多次垃圾回收仍然存活的对象,例如缓存对象,新建的对象也有可能在老年代上直接分配内存。主要有两种状况(由不同的GC实现来决定):一种为大对象,可通过在启动参数上设置-XX:PretenureSizeThreshold=1024(单位为字节,默认值为0)来代表当对象超过多大时就不在新生代分配,而是直接在老年代分配,此参数在新生代采用Parallel Scavenge GC时无效,Parallel Scavenge GC会根据运行状况决定什么对象直接在老年代上分配内存;另一种为大的数组对象,且数组中无引用外部对象。

新生代和老生代因为结构划分不一样,其串行收集器算法也不一样

新生代串行收集器

采用stop the world策略,步骤大概是:先从eden区扫描,把存活的对象拷贝到to区,如果to区放不下的对象直接拷贝到old区。再从from区扫描存活对象,如果对象存活次数超过阀值的就移到老年区,其他的移到to区。做完之后from和to区概念互换(from和to只是运行时的概念,其实就对应存活1区和存活2区)。

图形的表示如下:

回收前:

java 查看老年代新生代 jvm新生代和老年代_Java


回收后:

java 查看老年代新生代 jvm新生代和老年代_java 查看老年代新生代_02

老生代串行收集器
老生代垃圾回收主要分为三个阶段 Mark-sweep-compact
Mark:识别哪些是存活的
Sweep: 识别垃圾,并回收
Compact:滑动活动对象并压缩到连续空间,碎片整理。