一.架构设计
1.架构图
2.基本说明
1)程序计数器:线程私有,唯一没有OOM的区域
2)虚拟机栈:线程私有,基本类型,对象引用,请求深度大于所允许深度报栈溢出,
请求扩展内存不足,报内存溢出异常
3)本地方法栈:线程私有,为虚拟机提供Native方法服务,报OOM和栈溢出
4)堆:对象实例,无法扩展时报OOM
5)方法区:已被加载的类信息,常量,静态变量等数据。也会报OOM
6)运行时常量池:编译期生成的各种字面量(=右边的)和符号引用。
二. 垃圾收集器与内存分配策略
1.引用计数法:
被引用就加1,引用失效就减一(无法解决相互循环引用问题,虚拟机不采用)
2.可达性分析算法(主流):
被GCRoots对象引用链链到的对象不被回收
GCRoots:虚拟机栈中引用的对象
方法去中类静态属性引用的对象
方法去中常量引用的对象
本地方法栈中引用的对象
何时对象真正死亡:对象死亡有两次标记过程,第一次可达性分析对象可回收后,可以在
对象的finalize方法中链到其他对象求生。但是这个finalize方法只会
执行一次,故第二下发生第一次标记后,对象无能为力。 第二次
标记则是“即将回收”,对象等待被GC干掉。
3.引用分类:
强引用,Object o = new Object();(只要强引用还在,JVM不会回收的)
软引用,还有用但非必须,如快OOM,会回收,回收还不行则OOM,SoftReference来
实现软引用
弱引用,非必需对象,下次GC之前必死。WeakReference来实现
虚引用,对象是否有此引用对生存时间毫无影响,也无法通过虚引用获得对象实例,
唯一作用,被引用对象被回收时会有一个系统通知,PhantomReference实现
4.回收方法区:
常量回收:没有任何对象应用该常量则会被回收
类回收:满足a.该类所有实例都已经被回收,堆中无任何实例
b.该类的classLoader已经被回收
c.该类的Class对象没有在任何地方被引用,无法在任何地方通过反射
访问该类的方法
上述三点都满足则可以被回收,但不一定被回收,还需虚拟机参数配置
大量使用反射的框架需要配置回收类信息,防止方法区OOM
5.对象年代:见笔记初始截图
6.垃圾回收算法:
1)标记-清除算法:
标记出需要回收的对象,统一回收
缺点,会产生大量不连续的内存碎片
2)复制算法:内存一分为2,用完1份后,复制存活对象到2上,清空1,周而复始。
缺点,内存缩小为原来的一半,内存成本有点高
3)标记-整理算法:和标记清除类似,但不是直接回收,是活得往一端移动,只
回收一端边界以外的内存
4)分代收集算法:
将堆分为新生代和老年代,新生代用复制回收,老年代用标记清楚或
标记整理算法。因为新生代占的内存小
7.GC收集器:
1)Serial收集器:最老的收集器,单线程,垃圾回收时暂停其他的工作线程。
简单高效,是client端的Good choose
2)ParNew收集器:多线程版的Serial
3)Parrallel Scavenge收集器:复制算法+多线程的收集器,尽可能地减少收集时用户等
待时间
4)SerialOld收集器:Serial的老年版,使用标记整理算法
5)Parallel Old收集器:Parrallel的老年版,标记整理+多线程
6)CMS 收集器:广泛用于要求响应快的应用如互联网网站等B/S架构
标记清除算法,分4步:①初始标记②并发标记③重新标记④并发清除
7)G1收集器(多核多线程):①初始标记②并发标记③最终标记④筛选回收
8.内存分配和回收策略
1)新生对象再新生代Eden区,当Eden区没有足够空间进行分配时,虚拟机将发起一次
MinorGC.存活下的对象到Survivor (幸存者),Survivor分为两个部分,
To Survivor,From Survivor。Eden先到To Survivor,然后From Survivor
中的不能被回收的对象也到To Survivor,随后ToSurvivor和From Survivor
标记互换,保持有一个Survivor中为空。
old Gen(老年代),用于存放新生代中经过多次GC仍然存活的对象或者是新
生代无法存放的大对象。当老年代被放满后,虚拟机会进行Major GC又称
为Full GC.
major GC 比 minor GC 慢10倍以上。
未完待续.....