您的位置:首页 > 其它

JVM学习笔记(4)-内存分配与回收策略

2017-07-31 16:10 162 查看
在这里由于我的jdk环境是1.8的,JVM内存布局与1.7有很大的不同:

jdk1.7以及之前的java类信息,静态变量,常量池均保存在永久代中(Perm),类的元数据和静态变量在类加载的时候分配到 Perm,当类被卸载的时候垃圾收集器从 Perm 处理掉类的元数据和静态变量。当然常量池的东西也会在 Perm 垃圾收集的时候进行处理。

JDK 1.8 的对 JVM 架构的改造将类元数据放到本地内存中(非虚拟机中管理的内存),另外,将常量池和静态变量放到 Java 堆里。HotSopt VM 将会为类的元数据明确分配和释放本地内存。在这种架构下,类元信息就突破了原来 -XX:MaxPermSize 的限制,现在可以使用更多的本地内存。这样就从一定程度上解决了原来在运行时生成大量类的造成经常 Full GC 问题,如运行时使用反射、代理等。

GC的种类:

Minor GC:新生代GC

Major GC:老年代GC

Full GC:整个堆的GC

1.对象优先分配到Edge区





默认Edge:Survivor=8:1,分配了堆20M,新生代10M,剩下的老年代10M

可用新生代空间为Edge+1块Survivor  8192K+1024K

上面的例子中,byte1,byte2,byte3占了6M,byte4有4M在新生代放不下了(新生代只剩下3M了),触发垃圾回收,从Allocation Failure也可看出,在新生代发生了垃圾回收Minor GC;

在回收的时候发现survivor只有1024K无法装下2M的对象,将通过分配担保机制提前进入老年代,所以发现老年代已占用了60%,之后第四个对象byte4分配到Edge中 此时edge去占了54%,接近4M,注意这里不是刚好50%,因为存在数据对齐的原因。

如果设置在上面的设置中加入 -XX:SurvivorRatio=3

则Edge=6M,Survivor=2M

如下GC信息:



byte1和byte2正常分配到Edge中,主要这里虽然Edge有6M,byte1,byte2,byte3都为2M,看起来Edge能装下实际上是装不下的,次日志也可以看出4464k ->  255k这里也没有回收到0,在分配byte3=2M的时候发生Minor GC  这里回收的内存有byte1和byte2总共有4M,Survivor装不下通过分配担保机制提前进入老年代,byte3就可以分配到Edge中了,从第二次GC可以看出2303K装的就是2M的byte3,byte4又装不下了,再次出发Minor
GC。

2.空间分配担保机制

在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果成立,那么Minor GC是安全的。如果不成立,虚拟机会查找HandlerPromotionFailure设置值是否允许担保失败;如果允许虚拟机将检查老年代最大可用连续空间是否大于历次晋升到老年代对象的平均大小,如果大于将尝试一次Minor GC(尽管有风险);如果小于或者HandlerPromotionFailure设置不允许冒险则进行Full GC

然而在jdk1.6之后,虚拟机空间分配担保机制有改变:

只要老年代的可用的连续空间大于新生代对象总大小或者历次晋升的平均大小就进行Minor GC,否则进行Full GC
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JVM 虚拟机 内存分配