java内存分配策略

来源:互联网 发布:中学生网课平台知乎 编辑:程序博客网 时间:2024/05/21 07:56

java中的自动内存分配可以归结为两个问题:分配内存和回收内存。本文详细讲述分配内存这一问题。

概括的说,对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓存(TLAB),则优先在TLAB上分配,少数情况下会直接在老年代中分配。

内存分配规则取决于当前使用的是哪一种垃圾收集器组合以及虚拟机中内存相关的参数的设置。


详细来说

对象优先在Eden分配。当Eden区没有足够空间进行分配时,虚拟机会进行一次Minor GC。插入讲一下Minor GC和Full GC的区别。

新生代GC(Minor GC),指发生在新生代的垃圾回收动作,minor GC发生非常频繁,回收速度也非常快

老年代GC(Full GC/Major GC),指发生在老年代的GC,一般出现 Major GC会伴随着一次Minor GC,且回收速度较慢,是Minor GC的10倍。

大对象直接进入老年代。大对象是指需要大量连续内存空间的java对象,如很长的字符创或数组。虚拟机提供了一个-XX:PretenureSizeThreshold参数,令大于该值的对象直接在老年代分配,从而避免在Eden区及两个Survivor区之间发生大量的内存复制。

长期存活的对象将进入老年代。虚拟机为每个对象定义了一个对象年龄计数器。如果对象在Eden中出生并经过第一次Minor GC后仍然存活并且能够被Survivor容纳的话,那么该对象将被移动到Survivor中,并将该对象年龄设置为1。对象在Survivor中每经历一次Minor GC,年龄就加1,当其年龄增加到一定值(该值可以通过-XX:MaxTenuringThreshold进行设置,默认为15)时,将会被移动到老年代中。

但是也有例外。为了更好地适应不同程序的内存情况,虚拟机并不是永远要求对象的年龄必须达到了MaxTenuringThreshold才能移入老年代,如果在Survivor中,相同年龄的所有对象的大小总和大于Survivor空间的一般,那么年龄大于等于该年龄的所有对象就可以直接进入老年代。

空间担保分配。在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间。如果成立,那么可以保证Minor GC是安全的。如果不成立,则检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于则尝试进行一次Minor GC;否则,进行一次Full GC。

0 0
原创粉丝点击