【JVM】JVM是如何给对象分配内存的

内存分配图

在这里插入图片描述

对象栈上分配

JAVA中的对象都是在堆上进行分配的,当对象没有被引用时,需要进行CG进行回收内存,但是在对象数量非常多的时候,会进行对GC造成非常大的压力(频繁的进行GC,并且清理的对象数多),影响了应用的性能。在此基础上JVM针对性的进行优化,JVM通过逃逸分析来确定对象不会被外部访问,从而判断该对象可以在栈上分配内存,这样该对象所占用的内存空间就可以随着栈的销毁而销毁,减轻了垃圾回收的压力(GC)

对象逃逸分析:分析对象的动态作用域。

  • 当对象在方法中定义后,被外部方法引用

    public Heiheihei test(){
    	Heiheihei hei =new Heiheihei();
    	hei.setName("伞兵")
    	//其他操作
    	return hei;
    }
    

    该对象被返回,所以该对象的作用域范围不确定。无法判断是否被外部方法所引用。

  • 当对象定义后,不被外部方法引用

    public void  test(){
       	Heiheihei hei =new Heiheihei();
       	hei.setName("伞兵")
       	//其他操作
    }
    

    该对象没有被返回,可以确定没有被外部方法所引用。可以分配栈空间(内存)中,该对象随着栈内存一起被回收销毁。

    这种情况下可以通过参数-XX:+DoEscapeAnalysis来开启逃逸分析,通过标量替换优先分配栈上(栈上分配)

    注意:JDK7后默认开启逃逸分析,关闭参数为-XX:-DoEscapeAnalysis

标量替换

进行逃逸分析确定对象不会被外部访问,对象被进一步分解,JVM不会创建该对象,而是将该对象的成员变量分解成若干个被这个方法使用的成员变量进行替换,而这些替换的成员变量将会在栈帧或寄存器上分配空间,这样不会因为没有连续空间存储大对象而造成内存不够分配。

  • 开启标量替换:-XX:+EliminateAllocations,JDK7后默认开启

栈上分配依赖于逃逸分析和标量替换

对象在Eden区分配

绝大多少情况下,对象都在新生代的Eden区分配。而当Eden区没有空间进行分配时,JVM虚拟机将发起一次Minor GC。

补充

  • Minor GC/Young GC 发生在新生代的垃圾回收 ,Minor GC非常频繁,回收速度比较块。
  • Major GC/Full GC 发生在年轻代,老年代,方法区的垃圾回收,一般比 Minor GC慢10倍以上

过程

  • 大量的对象被分配到Eden区,当Eden区满了后触发minor gc ,大部分的对象成为垃圾被回收,剩余对象将会挪到空的Survivor区(幸存者一或二区),下一次Eden区满后将再次触发minor GC,将Eden区和survivor区的对象进行回收,存活对象挪动到另一块为空的Survivor区(幸存者一或二区)
  • 由于新生代对象存活下来对象非常少,存活时间短,所以JVM默认Eden:Survivor1:Survivor2比例为8:1:1 ,调节方面Eden区尽量的大,Survivor区够用即可.

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘿嘿嘿1212

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值