JAVA堆
线程共享的,存放所有对象实例和数组。垃圾回收的主要区域。可以分为新生代和老年代(tenured)。
新生代用于存放刚创建的对象以及年轻的对象,如果对象一直没有被回收,生存得足够长,老年对象就会被移入老年代。
新生代又可进一步细分为eden、survivorSpace0(s0,from space)、survivorSpace1(s1,to space)。刚创建的对象都放入eden,s0和s1都至少经过一次GC并幸存。如果幸存对象经过一定时间仍存在,则进入老年代(tenured)。
垃圾回收算法:
标记-清除算法(Mark-Sweep)
从根节点开始标记所有可达对象,其余没标记的即为垃圾对象,执行清除。但回收后的空间是不连续的。
复制算法(copying)
将内存分成两块,每次只使用其中一块,垃圾回收时,将标记的对象拷贝到另外一块中,然后完全清除原来使用的那块内存。复制后的空间是连续的。复制算法适用于新生代,因为垃圾对象多于存活对象,复制算法更高效。在新生代串行垃圾回收算法中,将eden中标记存活的对象拷贝未使用的s1中,s0中的年轻对象也进入s1,如果s1空间已满,则进入老年代;这样交替使用s0和s1。这种改进的复制算法,既保证了空间的连续性,有避免了大量的内存空间浪费。
标记整理(mark-sweep-compact)
适合用于老年代的算法(存活对象多于垃圾对象)。
标记后不复制,而是将存活对象压缩到内存的一端,然后清理边界外的所有对象。
- 新生代 GC(Minor GC):指发生在新生代的垃圾收集动作,因为 Java 对象大多都具
备朝生夕灭的特性,所以 Minor GC 非常频繁,一般回收速度也比较快。
- 老年代 GC(Major GC / Full GC):指发生在老年代的 GC,出现了 Major GC,经常
会伴随至少一次的 Minor GC(但非绝对的,在 ParallelScavenge 收集器的收集策略里
就有直接进行 Major GC 的策略选择过程) 。MajorGC 的速度一般会比 Minor GC 慢 10
倍以上。
- 对整个堆进行整理,包括Young、Tenured和Perm。Full GC比Scavenge GC要慢,因此应该尽可能减少Full GC。有如下原因可能导致Full GC:
* Tenured被写满
* System.gc()被显示调用