JVM对象内存分配

1 栈上分配
  • 空间随着方法执行完毕回收
  • 通过栈上分配对象内存空间方式减少对堆空间使用从而减少gc压力提升程序性能

  • 逃逸分析分析对象作用判断对象所需内存是否可以栈上分配
  • 对象没有外部方法或者对象引用对象可以栈上分配内存空间
  • 开启栈上分配jvm参数-XX:+DoEscapeAnalysis1.7默认开启

  • 标量替换通过将对象这样聚合量拆解一个基础数据这样标量达到栈上分配内存空间
  • 开启标量替换jvm参数-XX:+EliminateAllocations1.7默认开启
  • 通过逃逸分析可以栈上分配内存然后使用标量替换方式分配内存
  • 关闭逃逸分析或者标量替换任何一个jvm参数导致jvm跳过栈上分配直接堆中分配内存

  • 分配代码示例
public class App {
    private Integer a;
    private  int b;
    private Byte d;
    private byte e;
    public  static  void test(){
        App app = new App();
        app.a=1;
        test(app);
    }
   public static int test(App app) {
        int d = app.a;
        d++;
        return d;
    }
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            test();
        }
        System.out.println(System.currentTimeMillis()-start);
    }
}

设置jvm参数运行

-Xms15m -Xmx15M -XX:+PrintGCDetails -XX:+DoEscapeAnalysis -XX:+EliminateAllocations

观察基本不会发生GC执行耗时很短

调整jvm参数运行:

-Xms15m -Xmx15M -XX:+PrintGCDetails -XX:-DoEscapeAnalysis -XX:+EliminateAllocations

观察程序运行期间产生大量young gc执行耗时增高100多倍

2 大对象
  • 对象大小超过一定限制直接老年代分配内存
  • 设置大对象大小jvm参数-XX:PretenureSizeThreshold=1000000单位字节
  • 垃圾回收使用SerialParNew此参数才会生效

  • 代码示例
public static void main(String[] args) {
   byte[] bytes = new byte[10*1024*1024];
}

  • 设置jvm参数运行
-XX:+PrintCommandLineFlags -XX:PretenureSizeThreshold=1000 -XX:+PrintGCDetails -XX:+UseParNewGC

运行结果可知bytes对象老年代

3 动态年龄判断
  • 发生young gc之后,当幸存区域内某一批(gc年龄1~n之内的)对象大小占比幸存区超过50%之后,将gc年龄>=n的对象提早挪入老年代
  • 通过jvm参数-XX:TargetSurvivorRatio设置比例

4 老年代空间担保机制

  • 每次young gc之前jvm都会计算老年代剩余空间
  • 如果老年代剩余空间小于现在年轻代所有对象大小
  • 那么进一步判断之前每次young gc之后进入老年代对象平均大小是否大于老年代剩余空间
  • 如果大于剩余空间那么直接触发一次full gc
  • 进行young gc
  • 开启空间担保机制jvm参数-XX:+HandlePromotionFailure
  • jdk8实验报错已经不支持参数

5 长期存活的对象
  • 每发生一次young gc新生代内对象gc年龄就需要1
  • 对象gc年龄超过指定就需要搬运老年代
  • gc年龄阈值jvm参数-XX:MaxTenuringThreshold设置默认15

6 伊甸区
  • 一般情况下产生对象伊甸区分配内存
  • 空间不够触发一次young gc伊甸区正在使用幸存区存活对象搬运另外一块幸存
  • 临时对象尽可能让其young gc过程小汪
  • 默认情况下年轻代伊甸区幸存区比例8:1:1并且动态调整比例
  • 关闭动态调整jvm参数-XX:-UseAdaptiveSizePolicy默认开启
  • 调整伊甸区占用年轻代比例jvm参数-XX:SurvivorRatio=8

  • 证明年轻代空间不够但是老年代空间足够对象直接进入老年代
public static void main(String[] args) {
   {
      byte[] bytes1 = new byte[2*1024*1024];
   }
   byte[] bytes2 = new byte[4*1024*1024];
}

  • 增加jvm参数运行
-Xms15m -Xmx15M -XX:+PrintGCDetails

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值