-
内存分配策略
- 分配原则
优先分配到Eden
大对象可能直接被分配到老年代
为什么大对象直接被分配到老年代?
答:大对象一般是大的字符串或数组,大对象一般都不是朝生夕死的,它的存活时间比较长。因为新生代中垃圾回收算法一般采用复制算法,Eden区域执行gc频繁,若大对象存在于新生代中,每次执行gc都需要移动大对象,性能低,所以大对象放在老年代中,因为老年代gc次数比较少,性能好一些。
//设置成为大对象,进入老年代的阀值,当大于该值,则视为大对象进入老年代
-XX:PretenureSizeThreshold=8M
3.长期存活的对象可能被分配到老年代
//设置到达老年代存活的年龄阀值
//Survivor中有Age年龄计数器,每经过一次gc,存活下来的对象年龄+1,达到年龄阀值进入老年代
//jdk6之前默认年龄阀值为15,jdk6后长期存活年龄未必是15,也可能第2、3次就进入老年代了
-XX:MaxTenuringThreshold 15
4.创建对象时Eden区域内存不够,则会向老年代去借内存,即空间分配担保
//虚拟机默认启用空间分配担保,有一定风险
/*若垃圾回收采用复制算法,向老年代借用内存时候,虚拟机
*1、先检查老年代内存是否足够容纳下新生代的所有内存,若可以全部容纳下新生代的内存,则可以担保。
*2、检查参数是否开启 -XX:+HandlePromotionFailture +号开启 开启才能担保。
*3、验证老年代最大的可用连续空间是否大于历次竞争的老年代对象的平均值大小,大于平均值则担保。
*/
-XX:+HandlePromotionFailture
5.动态对象年龄判断
逃逸分析与栈上分配
逃逸分析 : 分析对象的作用域(如果对象被定义在方法体内部,他的作用范围就仅限于方法体内,若次对象只在方法内部有效(外部无引用此对象),则对象没有发生逃逸,可以被分配到栈内存上)————提高性能
package cn.itcats.jvm.memory.allocation;
/**
* 逃逸分析与栈上分配
*
* @author fatah
*/
public class Escape {
public Escape obj;
// 发生了逃逸,方法返回了Escape对象
public Escape getInstance() {
return obj == null ? new Escape() : obj;
}
// 发生逃逸,为成员属性赋值
public void setObj() {
this.obj = new Escape();
}
// 发生逃逸,引用成员变量的值
public void useEscapeValue() {
Escape escape = getInstance();
}
// 未发生逃逸,对象的作用域仅在当前方法有效
public void useEscape() {
Escape escape = new Escape();
}
}