测试JVM对象优先在Eden + From区域分配
package org.hujian.jvm.gc;
import org.hujian.common.JVMMemoryUnit;
import org.hujian.common.JvmTestRunner;
/**
* Created on 2018/11/1 22:05.
*
*
*/
public class TestEdenFirstAllocation extends JvmTestRunner {
/**
* 在这里实现测试逻辑,不提供参数列表以及返回值,执行该方法应该测试到
* 你需要实现的所有逻辑,本方法单线程执行(main)
*/
protected void execute() {
/**
* 测试点:
*
* 1、对象将优先在Eden里面进行分配,如果Eden区域没用足够空间进行分配时,JVM将
* 进行一次"Minor GC",也就是所谓的"Young GC"
* 2、"-XX:+PrintGCDetails"这个参数用于告诉JVM在发生GC的时候将内存回收日志
* 打印出来,便于分析GC行为
* 3、-Xms:20M 初始堆大小(初始堆大小 == 最大堆大小,代表堆不可扩展)
* -Xmx:20M 最大堆大小
* -Xms:128K 线程堆栈大小
* -Xmn:10M 新生代大小
* -XX:SurvivorRatio: 8 (代表Eden:s0:s1 = 8:1:1)
*
* JVM Arg: -XX:+UseConcMarkSweepGC -verbose:gc -XX:+PrintGCDetails -Xms20m -Xmx20m -Xmn10m -XX:SurvivorRatio=8
*/
byte[] data1, data2, data3, data4;
/// 堆大小总共20M,新生代10M,老年代10M
/// Eden : s0: s1 = 8:1:1,所以Eden大小为1024 * (8/10) = 8192; s0 = s1 = 1024
/// 所以Young区可以分配的空间大小为 Eden + s0 = 8192 + 1024 = 9216
/// data1 - data3: 在Eden区域可以正常分配,占用大小为6M = 1024 * 6 = 6144
/// data4请求分配4M大小的内存,但是Young区已经没有4M空间了,那么就只能进行一次"Minor GC"来清理Young区了
data1 = JVMMemoryUnit.MB.alloc(2);
data2 = JVMMemoryUnit.MB.alloc(2);
data3 = JVMMemoryUnit.MB.alloc(2);
data4 = JVMMemoryUnit.MB.alloc(4);
// 防止优化没了
System.out.println(data1[0] + data2[0] + data3[0] + data4[0]);
/// [GC (Allocation Failure)
// [DefNew: 8186K->408K(9216K), 0.0105397 secs]
// 8186K->6552K(19456K), 0.0106103 secs]
// [Times: user=0.01 sys=0.00, real=0.01 secs]
// 日志解读:首先说明了GC的原因是"Allocation Failure",然后DefNew则说明了GC发生的
// 堆区域,8186K->408K(9216K)中,8186K是GC前该区域使用量,408k代表GC后该区域使用量
// 括号内的9216k代表该区域的总大小;括号外的0.0105397 secs代表该区域的GC花费时间,之后的
// 8186K->6552K(19456K),表示堆区域GC前使用量,GC之后使用量以及堆大小
/// 这次GC发生的原因是在给data4分配内存的时候,发现Young区已没有4M空间提供分配了,所以需要进行
/// 一次Minor GC来回收垃圾,但是GC之后发现data1-data3都还存活着,那只能将这些存活的对象复制
/// 到S1中去(to区域),但是发现S1中内存不足以容纳任何大于1M的对象,所以JVM只好通过"分配担保"
/// 机制将这些对象提前转移到老年代中去
}
public static void main(String[] args) {
new TestEdenFirstAllocation().execute();
}
}