1.
-对象主要分配在新生代的Eden区
-如果启动了本地线程分配缓冲,按线程优先在TLAB上分配
-少数情况下也可能直接分配在老年代中,比如较大的对象
2.GC参数指定垃圾回收
-Xms20M jvm初始内存
-Xmx20M jvm最大内存
-Xmn10M jvm年轻代大小
这三个参数限制了java堆大小为20MB不可拓展,其中10MB
分配给新生代,剩下的10MB分配给老年代,一般我们将新生代老年代比列设置为为1:2
-Xx:SurvivorRatio=8决定了新生代中Eden区与两个Survivor区的
空间比例为8:1
3.
新生代GC(MinorGC) :发生在新生代的GC
老年代GC(MajorGC或者FullGC)
一般情况下,MajorGC比FullGC慢10倍以上
测试代码:
/**
* @Auther: jorian
* @Date: 2019/7/31 21:16
* @Description:
*/
public class JvmTest01 {
private static final int bsize = 1024*1024;
public static void main(String []args){
byte[] b =new byte[40*bsize];
}
}
配置启动参数: -verbose:gc -XX:+PrintGCDetails
可以看到使用的parllel scavenge的垃圾收集器
我们也可以指定使用串行的serial垃圾收集器: -verbose:gc -XX:+PrintGCDetails -XX:+UseSerialGC
可以看到,垃圾收集器已被修改,def就是指serial垃圾收集器
结论:基本分配原则:对象初始分配一般在新生代的Eden区
-所谓的大对象是指需要大量连续内存空间的java对象,最典型的大对象就是那种很长的字符串
以及数组
-虚拟机提供了一个-XX:PretennureSizeThreshold参数,令大于这个设置值的对象直接在老年代分配
这样避免了在新生代的Eden和Survivor区发生较大的内存复制
代码测试:
/**
* @Auther: jorian
* @Date: 2019/7/31 21:53
* @Description:
*/
public class JvmTest02 {
public static void main(String args[]){
byte[] bytes = new byte[1024*1024*10];//10M
}
}
设置启动参数:
-verbose:gc //开启GC日志
-XX:+PrintGCDetails //打印GC详情
-XX:+UseSerialGC //使用SerialGC
-XX:PretenureSizeThreshold=314728 //设置大对象阈值,超过即分配到老年代
-Xms20M -Xms20M -Xmx20M -Xmn10M
启动项目,结果:可以看到,老年代正好占用了10M,说明超过我们设置的3M阈值,对象分配到了老年代
逃逸分析:
逃逸分析的基本行为就是分析对象的动态作用域,当一个对象在方法中被定义后,它可能被外部方法所引用
,称为方法逃逸,甚至还有可能被外部线程访问到,比如赋值给类变量或可以在其他线程中访问的实例变量
,称为线程逃逸
栈上分配:
栈上分配就是把方法中的变量和对象分配到栈上,方法执行完后自动销毁,而且不需要垃圾回收的介入
从而提高系统性能。
栈上分配演练:代码:
/**
* @Auther: jorian
* @Date: 2019/7/31 22:18
* @Description:
*/
public class TestEscape {
public static Object obj;
public void variableEscape(){
obj = new Object(); //发生逃逸
}
public Object methodEscape(){
return new Object();//方法逃逸,不在方法里面了
}
public static void alloc(){
byte[] bytes = new byte[2];
bytes[0] = 1;
}
public static void main(String args[]){
Long start = System.currentTimeMillis();
//分配1000万次
for(int i = 0; i < 100000000; i++){
alloc();
}
Long end = System.currentTimeMillis();
System.out.println(end-start);
}
}
设置jvm启动参数,关闭jdk1.8默认开启的逃逸分析:-XX:-DoEscapeAnalysis
启动程序:可以看到时间为47
修改jvm启动参数,加上逃逸分析,-XX:+DoEscapeAnalysis
可以看到时间大幅缩小,时间为:15
如果开启了逃逸分析,就会进行栈上分配。
关闭逃逸分析,打开gc日志:
启动程序,发生了频繁的yongGC!!原因是内存不够分配。