深入JAVA虚拟机
原文链接 http://www.xiangguo.li/normal/2012/08/19/jvm
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。
{% include JB/setup %}
判断对象已经死的方法:1.引用计数法 2根搜索算法
GC Roots:
1 虚拟机栈(栈帧中的本地变量表)中的引用对象。
2 方法区中的类静态属性引用的对象。
3 方法区中的常量引用的对象。
4 本地方法栈中JNI(即一般说的Native方法)的引用的对象。
四种引用:
1.强引用只要引用还存在,垃圾收集器永远不会回收掉被引用的对象
2.软引用(SoftReference)用来描述一些还有用,但并非必需的对象。系统将要发生内存溢出异常之前,把这些对象进行回收。
3.弱引用(WeakReference)下一次垃圾回收发生时就会回收
4.虚引用(PhantomReference)相当于没引用,也不能通过虚引用获取一个对象的实例。为一个对象设置虚引用关联的唯一目的就是希望能在这个对象呗回收时收到一个系统通知。
Minor GC:新生代GC
Full GC:老年代GC
3.3垃圾收集算法
1.标记清除
缺点:一个是效率问题另外一个是空间问题,有碎片,会提前触发GC
2.复制
一块较大的Eden(8)和两个较小的Suivivor(1)。当Suivivor不够用时,向老年代借空间
3.标记整理
不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动。
4分带收集
新生代用复制,老年代用标记清除或者标记整理
3.4垃圾收集器
1.Serial收集器(复制)
优点:简单而高效,对于单个CPU的环境来说,没有线程交互的开销
缺点:单线程收集,停止时间长
2.ParNew
多线程的Serial(复制)
3.Parallel Scavenge收集器(复制)
吞吐量优先收集器,可设置最大垃圾手机停顿时间和直接设置吞吐量大小
停顿时间短,收集次数会增加,而且总的吞吐量变小
4.Serial Old
采用标记整理算法
5.Parrallel Old
6.CMS(Concurrent Mark Sweep)(标记清除,多次后整理)
初始标记
并发标记
重新标记
并发清除
缺点:
1.在单核CPU下会严重影响程序执行速度
2.在收集期间会产生新的垃圾(浮动垃圾),导致老年代空间必须预留一些空间
7.G1(标记整理)
原理:将Java堆分成固定大小区域,并且跟踪这些区域里面的垃圾堆积程度,在后台维护一张优先列表,每次根据允许的收集时间,优先回收垃圾最多的区域。
优点:无空间碎片,精确控制停顿,精确到毫秒。
3.5 内存分配和回收策略
3.5.1对象优先在Eden分配
3.5.2 大对象直接进入老年代-XX:PretenureSizeThreshold
3.5.3 长期存活的对象进入老年代-XX:MaxTenuringThreshold
3.5.4 动态对象年龄判定
如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。
3.5.5空间分配担保
在发生Minor GC时,虚拟机会检测之前每次晋升到老年代的平均大小是否大于老年代的剩余空间大小,如果大于,则改为直接进行一次Full GC,如果大于,则改为直接进行一次Full GC。如果小于,则查看HandlePromotionFailure设置是否允许担保失败;如果允许,那只好进行Minior GC;如果不允许,则也要改为进行一次Full GC.