JAVA对象的创建过程

JAVA 同时被 2 个专栏收录
39 篇文章 2 订阅
13 篇文章 1 订阅

今天分析一条指令:

Demo demo = new Demo();

这个Demo对象(普通对象)到底是咋来的?

来看一张图:

在图中可以清楚的看到jvm在创建对象时候的执行流程,下面具体讨论一下每个步骤:

在程序进行加载的时候,他的类信息,常量,静态变量等数据就会存放在方法区(常量池)中。

在执行new操作的时候,就会去方法区去寻找我们相应创建类的信息,如果找到的话执行下一步,

如果没有找到那么必须先执行类的初始化过程(加载,解析,初始化)

在类加载检查通过以后,开始为对象分配空间,通常由如下两种方法:

1.指针碰撞;

     当堆是绝对规整的,所有用过的放在一边,所有没用过的放在一边,中间放着一个指针作为分界的指示器,那么分配内存只需要将指针向空闲区域移动一段与对象同样大小的距离。

2.空闲列表;

     当堆中是是不规整的,使用的和未使用的内存相互交错,那么就无法进行简单的指针碰撞,这时候需要维护一个表,记录那些内存块是可用的,在分配的时候需要从列表中找出一块足够大的内存块分配给对象实例。

虚拟机如何分配内存是由堆上是否规整决定的。

思考一个问题:如果在多线程的情况下,创建对象时非常频繁的操作,那么怎么保证第一种方法的安全?

先说为什么不安全:当虚拟机正在给A分配内存,还没有来的及修改的时候,又开始给B分配内存,这样就造成了错误。

那么解决办法有两种:

1.利用锁的思想。

    即进行同步操作,在分配内存时进行锁定(加标记位),其他线程等待分配结束以后才能区访问。事实上虚拟机采用CAS(自旋)配上失败尝试的方式保证更新的原子性。

2.把内存分配按照线程分配在不同区域。

   每个线程在java堆中预先分配一块小内存,称为本地线程分配缓存栈(TLAB),哪个线程需要分配内存就在哪个线程的缓冲栈中分配。即设为线程私有的“堆”,

  当自己的缓存栈用完以后,就需要分配新的空间,那么这个时候就需要同步操作,防止出现与上面描述的错误。

  可以通过使用参数 -XX:+/-UseTLAB参数来设定。

 

内存分配完以后,虚拟机会将分配到的内存空间都置为零值(不包括对象头),这一步保证了对象的实例字段在JAVA中可以不用赋初值就可以直接使用。

最后就是虚拟机进行必要的配置了,类的元数据信息,哈希码,GC分代年龄等信息。

这样一个对象就创建完成了,但是在java程序的角度来说,这刚刚开始 ---<init()>方法还没执行。

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页

打赏

骚小孩呀

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值