目录
技术到了一定的程度,总是想要进一步的提高,但是有时候苦于网上的资料参差不齐,有些更是让人只知其表,我本人是找不到比较好的方法来打开新的道路。又苦于前方路途迷茫,有时也是看着各大V推荐的书籍进行阅读,和在学校一样,读书读不进去,写代码倒是飞快。开了blog,那就一点一滴记录下来吧
垃圾收集算法
标记-清除算法:
其他算法改进的基础
标记处需要回收的对象,标记完成后统一回收所有被标记的对象
缺点:效率问题、空间问题
复制算法:
过程:将内存分为两块,每次使用一块,用完后将存活的复制到另外一边,然后把这边清空
目前在回收新生代的时候使用,Eden+survivor1→survivor2,然后清除掉Eden+survivor1
Eden:survivor1:survivor2 = 8:1:1(每次只要10%来承载,不够时向Old转移)
标记-整理算法:
对于存活率较高的,极端100%存活,拷贝就不划算了
只不过是不是直接清除标记,而是向一端移动,然后再清除
分代收集算法:
就是指上面的(新生代)复制算法、(老年代)标记-整理算法
垃圾收集器
Serial 收集器:
JDK1.3之前的唯一选择,单线程收集器(Stop The World)
Client模式下是一个很好的选择
ParNew 收集器(-XX:+UseConcMarkSweepGC、-XX:+UseParNewGC):
主要用在新生代收集器,除了Serial之外只有他能和CMS搭配使用
在单核环境下绝对不如Serial,默认开启的线程与CPU核数相同(-XX:ParallelGCThreads限制线程数)
并行:指多条GC线程并行工作,此时用户线程仍在等待
并发:指用户线程和GC线程同时工作,可能是交替进行的
Parallel Scavenge收集器:
主要用在新生代收集器,使用复制算法的并行多线程收集器
与其他GC收集器不同在于:达到一个可控制的吞吐量(用户CPU/(用户CPU+GC使用CPU)),主要是和后台运算不需要太多交互的业务
-XX:MaxGCPauseMillis:停顿时间、-XX:GCTimeRatio:吞吐量大小;这两是相互平衡
-XX:UseAdaptiveSizePolicy:不需要手工配置比例,自适应(与ParNew收集器最大的区别)
Serial Old收集器:
是Serial收集器的老年代版本,使用”标记-整理“算法
Client模式下使用
server模式下:
1.在JDK1.5及以前与Parallel Scavenge收集器搭配使用
2.作为CMS收集器的后备方案,在Concurrent Mode Failure时候使用
Parallel Old收集器:
Parallel Old是Parallel Scavenge的老年代版本,使用多线程和”标记-整理“算法
Parallel Scavenge+Parallel Old用于注重吞吐率和CPU敏感的场合
CMS 收集器:
Concurrent Mark Sweep以最短回收停顿时间为目标的收集器,并发收集、低停顿,使用”标记-清除“算法
初始标记、Stop The World:标记GC Roots直接关联到的对象
并发标记、Root Tracing过程
重新标记、Stop The World:修正并发标记期间用户程序导致变动的部分
并发清除、
缺点:
1.CMS对CPU资源敏感(CPU+3)/ 4,虚拟机提供抢占式技术
2.CMS收集器无法处理浮动垃圾,因为并发需要预留空间(69%就被激活)
3.由于基于”标记-清除“,所以产生大量碎片(-XX:+UseCMSCompactAtFullCollection整理开关、-XX:CMSFullGCsBeforeCompaction次数)
G1 收集器:
基于”标记-整理“算法实现
精准控制停顿:让使用者指定长度M毫秒内,垃圾收集时间不得超过N秒(几乎实时Java(RTSJ)收集器特征)
实现:
G1将整个Java堆(包括新生代、老年代)划分为多个大小固定的区域(Region)
跟踪这些Region的垃圾程度,后台维护一个优先列表
根据允许收集的时间,优先回收垃圾最多的区域(Garbage First的由来)
垃圾收集参数:
内存分配与回收策略
对象优先在Eden分配:
对象在新生代Eden区分配,当没有足够空间时触发Monitor GC(-XX:+PrintGCDetails)
-XX:SurvivorRatio=8:Eden : Survivor = 8 : 1
Minor GC:频繁,回收速度快
Major GC/Full GC:经常伴随着MinorGC,一般慢10倍以上相对新生代
大对象直接进入老年代:
大对象指的是需要连续空间的Java对象,eg:长字符串和数组
(-XX:PretenureSizeThreshold 大于它直接进入老年代)这个参数只对于Serial和ParNew收集器有效
长期存活的对象进入老年代:
每个对象定义了一个(Age)计数器,每渡过一次Minor GC年龄加1,>15进入老年代
(-XX:MaxTenuringThreshold设置Age的大小)
动态年龄判定:
Survivor空间相同年龄的对象大小总和大于Survivor空间的一半,年龄大于或等于该年龄的对象直接进入老年代
空间分配担保:
在进行MinorGC的时候,会检测老年的平均对象大小是否大于老年代的剩余大小
大于直接FullGC
小于,查看HandlePromotionFailure设置是否允许担保失败,允许则只进行MinorGC在MinorGC极端情况,全部存活需拷贝进老年代,老年代需要判断有多少对象能活下来,则与之前的Old区域的平均对象大小判断是否进行FullGC