网站制作实验报告,洛阳网站建设制作多少钱,在wordpress上添加播放,网站建设电销目前主流的垃圾收集器都会采用分代回收算法#xff0c;因此需要将堆内存分为新生代和老年代#xff0c;这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。
大多数情况下#xff0c;对象在新生代中 eden 区分配。当 eden 区没有足够空间进行分配时#xff0c;虚拟…目前主流的垃圾收集器都会采用分代回收算法因此需要将堆内存分为新生代和老年代这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。
大多数情况下对象在新生代中 eden 区分配。当 eden 区没有足够空间进行分配时虚拟机将发起一次 Minor GC.下面我们来进行实际测试以下。
在测试之前我们先来看看 Minor GC 和 Full GC 有什么不同呢
新生代 GCMinor GC:指发生新生代的的垃圾收集动作Minor GC 非常频繁回收速度一般也比较快。老年代 GCMajor GC/Full GC:指发生在老年代的 GC出现了 Major GC 经常会伴随至少一次的 Minor GC并非绝对Major GC 的速度一般会比 Minor GC 的慢 10 倍以上。
测试
public class GCTest {public static void main(String[] args) {byte[] allocation1, allocation2;allocation1 new byte[30900*1024];//allocation2 new byte[900*1024];}
}
通过以下方式运行
添加的参数-XX:PrintGCDetails
运行结果 (红色字体描述有误应该是对应于 JDK1.7 的永久代) 从上图我们可以看出 eden 区内存几乎已经被分配完全即使程序什么也不做新生代也会使用 2000 多 k 内存。假如我们再为 allocation2 分配内存会出现什么情况呢
allocation2 new byte[900*1024]; 简单解释一下为什么会出现这种情况 因为给 allocation2 分配内存的时候 eden 区内存几乎已经被分配完了我们刚刚讲了当 Eden 区没有足够空间进行分配时虚拟机将发起一次 Minor GC.GC 期间虚拟机又发现 allocation1 无法存入 Survivor 空间所以只好通过 分配担保机制 把新生代的对象提前转移到老年代中去老年代上的空间足够存放 allocation1所以不会出现 Full GC。执行 Minor GC 后后面分配的对象如果能够存在 eden 区的话还是会在 eden 区分配内存。可以执行如下代码验证
public class GCTest {public static void main(String[] args) {byte[] allocation1, allocation2,allocation3,allocation4,allocation5;allocation1 new byte[32000*1024];allocation2 new byte[1000*1024];allocation3 new byte[1000*1024];allocation4 new byte[1000*1024];allocation5 new byte[1000*1024];}
}大对象直接进入老年代
大对象就是需要大量连续内存空间的对象比如字符串、数组。
为什么要这样呢
为了避免为大对象分配内存时由于分配担保机制带来的复制而降低效率。
private static final int _1MB 1024 * 1024;/*** VM参数-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:PrintGCDetails -XX:SurvivorRatio8* -XX:PretenureSizeThreshold3145728*/
public static void testPretenureSizeThreshold() {byte[] allocation;allocation new byte[4 * _1MB]; //直接分配在老年代中
}
执行后我们发现新生代几乎没有被使用老年代被使用了40%因为超过一定数值的对象就会直接被分配到老年代。
长期存活的对象进入老年代
既然虚拟机采用了分代收集的思想来管理内存那么内存回收时就必须能识别哪些对象应放在新生代哪些对象应放在老年代中。为了做到这一点虚拟机给每个对象一个对象年龄Age计数器。
如果对象在 Eden 出生并经过第一次 Minor GC 后仍然能够存活并且能被 Survivor 容纳的话将被移动到 Survivor 空间中并将对象年龄设为 1.对象在 Survivor 中每熬过一次 MinorGC,年龄就增加 1 岁当它的年龄增加到一定程度默认为 15 岁就会被晋升到老年代中。对象晋升到老年代的年龄阈值可以通过参数 -XX:MaxTenuringThreshold 来设置。
private static final int _1MB 1024 * 1024;/*** VM参数-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:PrintGCDetails -XX:SurvivorRatio8 -XX:MaxTenuringThreshold1* -XX:PrintTenuringDistribution*/
SuppressWarnings(unused)
public static void testTenuringThreshold() {byte[] allocation1, allocation2, allocation3;allocation1 new byte[_1MB / 4]; // 什么时候进入老年代决定于XX:MaxTenuringThreshold设置allocation2 new byte[4 * _1MB];allocation3 new byte[4 * _1MB];allocation3 null;allocation3 new byte[4 * _1MB];
}
年龄判定
为了更好的适应不同程序的内存情况虚拟机不是永远要求对象年龄必须达到了某个值才能进入老年代如果 Survivor 空间中相同年龄所有对象大小的总和大于 Survivor 空间的一半年龄大于或等于该年龄的对象就可以直接进入老年代无需达到要求的年龄。
分配担保