java内存分析 - xiaofa307/store GitHub Wiki
垃圾回收
引用计数(简单但速度很慢,从未被应用于任何一种java虚拟机实现中)
每个对象含有一个引用计数器,当有引用连接至对象时,引用计数加1。当引用离开作用域或被置为null时,引用计数减1. 缺陷:对象之间存在循环引用的时候会出现"对象应该被回收,但引用计数却不为零"的情况。
自适应的、分代的、停止-复制、标记清扫式垃圾回收器(sun早期)
停止-复制:先暂停程序的运行(所以他不属于后台回收模式),然后将所有存活的对象从当前堆复制到另一个堆,没有被复制的全是垃圾,当对象被复制到新堆时,他们是一个挨一个的,所以新堆保持紧凑排列。 对于这种"复制式"回收器而言,效率会降低
- 首先得有两个堆,然后在这两个分离的堆之间来回倒腾,从而维护比实际多一倍的空间
- 程序进入稳定状态后,可能只产生少量垃圾,尽管如此,"复制式回收器"仍然将所有内存自一处复制到另一处,为了避免这种情况,一些java虚拟机会进行检查:要是没有新垃圾产生,就会转到另一种模式(此为"自适应")。这种模式为标记-清扫(sun公司早期版本的java虚拟机使用了这种技术),一般而言标记-清扫模式只有在你知道只会产生少量垃圾时速度才快。
标记-清扫:从堆栈和静态存储区出发,遍历所有引用,进而找出存活对象并标记存活对象,当全部标记完成的时候,清理动作才会开始,在清理过程中,没有标记的对象被释放。所以剩下的堆空间是不连续的。 from think in java 第四版,5.5.4节
分代垃圾收集(新生代回收频繁需要时间快,老年代占用空间大需要空间大)
新生代(也称次要垃圾收集,记作minor GC)
新生代空间小且收集频繁,存放新分配的对象,长期存活的对象最后被提升(promote或tenure)到老年代。
老年代(也称主要垃圾收集或完全垃圾收集,记作full GC)
执行频率低,但是一旦发生,执行时间就会很长。
永久代(用来存储元数据,如类的数据结构、保留字符串等) 用户创建的对象最终不会从老年代移送到永久代