您的位置:首页 > 其它

JVM垃圾回收和内存分配策略

2016-04-19 11:42 357 查看

JVM的垃圾回收

JVM垃圾回收主要完成以下几个方面的工作:

哪些内存需要回收

什么时候回收

怎么回收

问题一,有两个子问题需要回答

JVM内存布局中哪些部分进行垃圾回收?

程序计数器、虚拟机栈、本地方法栈三个区域是与线程紧密相关的,每个栈帧分配的内存大小在编译期是可知的,并且会随着线程的结束而释放相应的内存。堆区和方法区所需的内存随着程序的运行而动态变化,是垃圾回收的主要区域。

对象何时可以被回收?(对象存活判定算法

即对象存活性判定问题。主要有两种策略来决定对象的“死与活”, 引用计数法和可达性分析法。

引用计数法:为每个对象添加一个引用计数器,当引用计数器计数到0时,对象就不可能再被使用了。这种方法很直观,但是对对象间相互循环引用的情况不能进行垃圾回收。

可达性分析法:从一系列的GCRootSet中的对象开始,根据引用关系构建引用关系链,在这些引用关系链中的对象是可达的,否则是不可达的。

GCRootSet中的对象主要包括:方法栈帧中引用的对象、类的静态成员引用的对象,方法区中常量引用的对象,本地方法栈中引用的对象。

问题二,垃圾回收的时间

JVM中存在固定的垃圾回收线程,在某些时间执行垃圾回收算法。对不可达的对象,要经过两次标记过程:

第一次,被标记并筛选,筛选准则是是否有必要执行finalize()方法。

对于判定为有必要执行finalize()方法的对象,添加到F-Queue的队列中,并稍后由Finalizer线程去执行,(不承诺等它结束)。

第二次,回收 “即将回收”集合中的对象。

问题三,垃圾收集算法

标记-清除算法

标记过程就是判定对象是否可达的过程,清除即回收对应的区域。最基础的算法,缺点:效率问题,内存碎片。

复制算法

将可用内存空间分为大小相等的两块,每次只使用其中一块。当这一块内存即将用完时,将其中的存活对象复制到另外一块中去,并一次性清空本块内存。

改进:根据%98对象都是朝生夕死,原理。新生代维持%10的空闲区(Eden + 2 Survivor),不够时由老年代分配担保。

标记-整理算法

适用于老年代中(多数对象都存活), 先标记,然后让所有对象向一端移动,清理掉端边界以外的对象。

分代收集算法

将堆分为新生代、老年代。老年代:标记整理算法,新生代:复制算法。

安全点(Safe Point): GC垃圾回收的暂停点。

垃圾收集器:实例

Serial收集器:单线程,Stop the World.

SerialOld:

ParNew收集器:Serial的多线程版本。

Parallel Scavenge 收集器:以吞吐量为控制目标。

停顿时间和吞吐量的矛盾:停顿时间关系到交互效果,吞吐量关系到CPU利用效率。减小新生代空间可以减小停顿时间,但是回收频率必须变高,因此吞吐量变小了。

ParallelOld: 用于老年代,控制吞吐量。

CMS:并发收集,低停顿。

G1收集器:

分配策略:对象优先在Eden区域,大对象直接进入老年代,长期存活的对象进入老年代(年龄阈值),动态年龄判定,空间分配担保。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jvm 虚拟机 内存 对象