java eden survivor分配 怎么给java分配内存_JVM

1.栈上分配

通过 JVM 内存分配,可知 JAVA 中对象一般都在分配至堆内存。当对象没有被引用时,需依靠 GC 进行内存回收;若对象数量较多,则会给GC带来较大压力,也间接影响了应用的性能。

JVM 通过逃逸分析将非逃逸的临时小对象(因为栈空间较小,默认1M左右),放在栈上分配。

好处:对象所占内存空间可随栈帧出栈而销毁,减轻垃圾回收压力

●依赖:逃逸分析和标量替换

2.老年代分配

2.1 大对象直接进入老年代

大对象就是需要大量连续内存空间的对象(比如:字符串、数组)。

JVM参数 -XX:PretenureSizeThreshold 可以设置大对象的大小,如果对象超过设置大小会直接进入老年代,不会进入年轻代,这个参数只在 Serial 和ParNew两个收集器下有效。其他垃圾收集器是另外的参数来设置。

比如设置JVM参数:-XX:PretenureSizeThreshold=1000000 (单位是字节) -XX:+UseSerialGC ,程序的超过设置值的大对象会直接进老年代

为什么要这样呢?

为了避免为大对象分配内存时的复制操作而降低效率。

2.2 长期存活的对象将进入老年代

虚拟机为保证内存回收时,识别哪些对象应放在新生代,哪些对象应放在老年代中,而给每个对象一个对象年龄(Age)计数器。

若对象在 Eden 出生并经过第一次 Minor GC 后仍存活,且能被 Survivor 容纳,该对象被移动到 Survivor 空间,同时该对象年龄设为1。

对象在 Survivor 中每熬过一次 MinorGC,年龄就增加1,当它的年龄增加到一定程度(默认为15岁,CMS收集器默认6岁,不同的垃圾收集器会略微有点不同),就会被放到老年代。

对象晋升到老年代的年龄阈值,可以通过参数 -XX:MaxTenuringThreshold 来设置。

2.3 对象动态年龄判断

当前存放对象的 Survivor 区里(其中一块区域,准备存放对象的那块S区),一批对象的总大小大于这块Survivor 区域内存大小的50%(-XX:TargetSurvivorRatio 参数可以指定),那么此时大于等于这批对象年龄最大值的对象,就可以直接进入老年代了;

例如 Survivor 区域里现在有一批对象,年龄1+年龄2+...+年龄n的多个年龄对象总和超过了 Survivor 区域的50%,此时就会把年龄n(含)以上的对象都放入老年代。

这个规则其实是希望那些可能是长期存活的对象,尽早进入老年代。对象动态年龄判断机制一般是在Minor GC 之后触发的。

3. Eden 分配

大多数情况下,对象在新生代中 Eden 区分配。当 Eden 区没有足够空间进行分配时,虚拟机发起 Minor GC。

3.1 TLAB 分配

TLAB,全称 Thread Local Allocation Buffer,即线程本地分配缓存。是一块 线程专用 的内存分配区域。TLAB 占用的是 eden 区的空间,在 TLAB 启用的情况下(默认开启),JVM 会为每一个线程分配一块私有缓存区域区域,即为 TLAB 内存区域。

参数

作用

备注

-XX:+UseTLAB

启用 TLAB

默认启用

-XX:TLABRefillWasteFraction

设置允许空间浪费的比例

默认值:64,即使用 1/64 的 TLAB 空间大小作为 refill_waste

-XX:TLABWasteTargetPercent

设置 TLAB 空间所占用 Eden 空间的百分比大小

默认 1,即占用 Eden 空间 1 %

-XX:-ResizeTLAB

禁止系统自动调整 TLAB 大小

-XX:TLABSize

指定 TLAB 大小

单位:B

其中,-XX:TLABRefillWasteFraction 指当 TLAB 空间不足,请求分配的对象内存大小超过此阈值时不会进行 TLAB 分配,直接进行堆内存分配,否则还是会优先进行 TLAB 分配。

3.3 Eden 分配

Eden 与 Survivor 区默认8:1:1,Eden 区满后触发 Minor GC。

可能有99%以上的对象成为垃圾被回收掉,剩余存活对象被挪到为空的那块 Survivor 区;

下一次 Eden 区满后又触发 Minor GC,把 Eden 区和 Survivor 区垃圾对象回收,剩余存活的对象被一次性挪动到另外一块为空的 Survivor 区。

因为新生代的对象都是朝生夕死的,存活时间很短,所以 JVM 默认的8:1:1的比例很合适,让 Eden 区尽量的大,Survivor 区够用即可。

JVM 参数:-XX:+UseAdaptiveSizePolicy(默认开启),会导致这个8:1:1比例自动变化,如果不想这个比例有变化可以设置参数-XX:-UseAdaptiveSizePolicy