天天看点

jvm(10) -- 内存分配策略

文章目录

  • ​​内存分配策略​​
  • ​​0.概述​​
  • ​​1.内存分配优先进入eden区域​​
  • ​​2.大对象直接进入老年代​​
  • ​​3.长期存活的对象直接进入老年代​​
  • ​​4.空间分配担保​​
  • ​​5.逃逸分析和栈上分配​​
  • ​​如何查看逃逸分析的筛选结果​​
  • ​​6.TLAB 线程本地分配缓存​​

内存分配策略

0.概述

jvm(10) -- 内存分配策略

1.内存分配优先进入eden区域

jvm(10) -- 内存分配策略

​-verbose:gc -XX:+PrintGCDetails -XX:+UseSerialGC​

jvm(10) -- 内存分配策略
java -version
jvm(10) -- 内存分配策略

多核,2个G以上的cpu都认为是server vm。

操作1:

jvm(10) -- 内存分配策略

操作2:

jvm(10) -- 内存分配策略

说明大对象直接在老年代分配内存。

操作3:

jvm(10) -- 内存分配策略

设置vm参数:

-verbose:gc

-XX:+PrintGCDetails

-XX:+UseSerialGC

-Xms20M

-Xmx20M

-Xmn10M

-XX:SurvivorRatio=8

jvm(10) -- 内存分配策略

堆一共才20M大小,给他40M,肯定会内存溢出。

操作4:

jvm(10) -- 内存分配策略
jvm(10) -- 内存分配策略

内存担保,eden区只能存8M,先存3个2M到eden,后面的4M来了,存不了,得放survior区,一个suvivior才1m,于是向老年代借空间,把原来的6m存在老年代。

这个4m根据eden优先原则,存在eden区。

2.大对象直接进入老年代

虚拟机提供了一个-XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代分配。

PretenureSizeThreshold参数只对Serial和ParNew两款收集器有效,Parallel Scavenge收集器不认识这个参数,Parallel Scavenge收集器一般并不需要设置。如果遇到必须使用此参数的场合,可以考虑ParNew加CMS的收集器组合。

操作:

指定前:

jvm(10) -- 内存分配策略
jvm(10) -- 内存分配策略
指定多大内存到老年代
jvm(10) -- 内存分配策略
jvm(10) -- 内存分配策略

3.长期存活的对象直接进入老年代

jvm(10) -- 内存分配策略
jvm(10) -- 内存分配策略
jvm(10) -- 内存分配策略

通过上面的参数设置,到底多大的年龄进入老年代。

4.空间分配担保

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

JDK 6 Update 24 之后,HandlePromotionFailure参数不会再影响到虚拟机空间分配担保的策略,规则变为只要老年代的连续空间大于新生代对象总大小或者大于历次晋升对象大小的平均值就会进行Minor GC ,否则将进行Full GC。

5.逃逸分析和栈上分配

讲的比较好

发生逃逸的不要用栈上分配。

如何查看逃逸分析的筛选结果

参考:链接:https://www.jianshu.com/p/f1e5e03ed2f8

可以通过配置 -XX:+PrintEscapeAnalysis 开启打印逃逸分析筛选结果

栈上分配需要有一定的前提

  • 开启逃逸分析 (-XX:+DoEscapeAnalysis)

逃逸分析的作用就是分析对象的作用域是否会逃逸出方法之外,再server虚拟机模式下才可以开启(jdk1.6默认开启)

  • 开启标量替换 (-XX:+EliminateAllocations)

标量替换的作用是允许将对象根据属性打散后分配再栈上,默认该配置为开启

6.TLAB 线程本地分配缓存

全称叫做:Thread Local Allocation Buffer 即线程本地分配缓存

那么能不能构造一种线程私有的堆空间,哪怕这块堆空间特别小,但是只要有,就可以每个线程在分配对象到堆空间时,先分配到自己所属的那一块堆空间中,避免同步带来的效率问题,从而提高分配效率。