Jvm创建对象之内存分配-JVM(七)

上篇文章介绍了jvm创建,会校验是否已加载类,没有则加载,通过之前学的源码,classLoader加载完之后,虚拟机开始给类分配内存,指针移动分配和free链表分配,解决并发分配情况用cap和TLAB方法。之后设置对象头部信息,有mark word线程锁,分代年龄等,klass pointer。还有指针压缩的概念。

Jvm对象创建-JVM(六)
  • 指针压缩的好处?
  1. 在64位平台的HotSpot使用,则会内存多使用一倍,占用较大带宽,gc也会压力增大。
  2. 堆内存小于4g(2^32)的时候会自动指针压缩。
  3. 堆内存大于32g的时候会指针压缩无效。

-XX:+UseCompressedClassPointer只会压缩klassPointer指针

  • 逃逸分析

当我们一个方法里面创建一个新的对象,如果这个对象return,则会在方法外部被调用,如果没有return,则只会在方法内部调用,这种则就称为方法逃逸。

第二种只在方法内调用,可以把他分配在栈内存里面,随着栈内存的回收一起被gc。

默认是开启逃逸分析,如果关闭则使用

-XX:-DoEscapeAnalysis

  • 标量替换,聚合量

当一个对象通过逃逸分析确定不会逃逸,也就是不会被外部调用时候,这时候jvm不会创建该对象,而是将该对象分解若干个方法使用成员变量替换,这样就不会因为一大块连续的内存空间而导致不够用。

Jdk1.7之后默认开启标量替换,关闭则使用

-XX:+EliminateAllocations

(标量就是不可拆分的量,比如int,long)标量对立就是可以被进一步分解的量,叫聚合量,可以被继续分解。

 

由上可以知道,我们是先在栈上分配,因为前面说的逃逸分析,标量替换,之后再往堆分配。

那栈里怎么会放那么多对象呢?

比如一个main方法里调用一个方法,这个main方法有一个大的栈空间,里面的方法会有一个栈帧空间,而这个方法结束的时候,线程会退出,这时候栈帧空间就会释放,所以后面就继续可以使用栈帧空间。

  • EDEN

如果对象太大,则会直接进入old代里。

 

我们需要在启动的时候加参数:-XX:+PrintGCDetails

这时候放入45M的数据(1024byte=1kb,1024kb=1m)

可以看到eden已经满了,eden区一共有50m的空间,足够放的下,YoungGen区从图中可以看到有60M的空间。

后面的from和to都是百分之0,oldGen也是百分之0。

 

我们再放入7M的数据让内存分配,这时候可以看到eden和from都有放。

放不下则放入oldGen老年代,老年代有45M左右。

前面的45M全部到老年代了,后面新进入的7M则在eden。

 

当我们再放3M进去可以看到,还是进入了eden。老年代放的还是刚刚的大对象。

对象是在eden分配的,当我们放不下的时候,会生成yongGC也就是MinorGC,新生代回收频繁,速度比较快。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

后端从入门到精通

你的鼓励是我最大的动力~

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

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

打赏作者

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

抵扣说明:

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

余额充值