垃圾回收器是垃圾回收算法的实现,Java虚拟机的设计者为了
获取最大的性价比,也在不断改进中。硬件在不断变化,多核
的普及,基于单核的收集器应该已经没有太大意义了。Java7中
又新增了g1收集器,没具体研究,【不明觉厉】啊。
暂时觉得垃圾器的细节不用深入研究,性能问题卡到垃圾收集,应该
考虑的是编写的程序质量而不是垃圾回收的性能。
下面介绍垃圾回收的一些原则:
(1) 对象先在eden上分配。
如果eden上剩余空间无法容纳新建立的
对象,则发起一次新生代的垃圾回收。过程是把eden和survivor from
上存活的对象放入survivor to上,之后清理eden和survivor区域。当然,
原来的survivor from变成了survivor to区域,而survivor to变成了
survivor from区域。
(2)大对象直接进入老生代。
如果有些大对象一直在新生代中用复制
算法拷贝来拷贝去,也是很大的性能浪费,索性不如直接扔到老生代
侯着。(老生代没有新生代垃圾回收的那么频繁,当然老生代收集一次
的花销要远远大于新生代)
虚拟机提供了参数,可以控制大对象的阀值。这样只要大于所配置
的阀值,自动把对象分配到老生代上。
个人认为大对象者,因为需要连续空间应该只要发生在大数组情况下。
ArrayList的底层实现也是数组,这个需要注意。当然也不排除有人把
一个类中写了n多属性,光引用或者基本类型就构成一个大对象,这个
应该很少见。
书上没写虚拟机默认的大对象阀值是多少,亦或如果不手动加入这个
限制,虚拟机是不设上限的?
(3)长期存活对象进入老生代。
有些对象一直存活不能被回收,但是新生代每次垃圾回收都能容纳这种
对象,这样会造成复制的性能浪费。所以,虚拟机给每个对象设了对象
年龄这么个属性,好像这个值是存在对象头中的。对象新生成时,年龄
设为一,之后在每次新生代的收集中如果能躲过一劫,则年龄加一。
虚拟机的默认阀值是15,当一个对象的年龄大于15,将被请如网址:yii666.com
老生代名人堂。这个阀值可以设置。
(4)动态对象年龄判定 虚拟机有一个策略,如果survivor
中相同年龄的所有对象的大小的总和大于survivor空间的一半,
年龄大于或者等于该年龄的对象就可以直接进入老年代,无须
等到maxtenuringthreshold中要求的年龄。
策略明白,但是好处是什么?作者没举例,我自己想了几个
例子,不一会又被自己推翻了,姑且相信实现虚拟机垃圾回收的
高手。因为是高手啊!
(5)空间分配担保
在发生新生代minor gc时,虚拟机会检测之前每次晋升到老
生代的平均大小是否大于老生代的剩余空间大小。如果大于,
则改为直接进行一次老生代full gc。如果小于,则查看担保设置
是否允许失败,如不允许则会伴随一次full gc。
为避免full gc过于频繁,担保失败开关一般是打开的。
取平均值比较是动态概率的手段,并不能保证担保不失败。
担保失败后,仍然需要进行一次 full gc。
作者说担保失败后在full gc绕的圈子是最大的,但是我
不甚明白,同样是进行一次full gc,时机的不同会造成
效率的不同?这个问题有机会再查。
后面这两点作者只是给出了,这种情况出现的例子,但是文章来源地址:https://www.yii666.com/article/758017.html
没有说出这样做的好处,感觉有点应付(^_^)文章地址https://www.yii666.com/article/758017.html