zoukankan      html  css  js  c++  java
  • JVM理论:(一/1)对象的创建过程

    一、对象的创建

    1、当虚拟机遇到一条new指令时,会先检查常量池中能否定位到这个类的符号引用,然后检查这个符号引用代表的类是否被加载、解析、初始化过。

    2、如果类还未加载过,要先执行类加载过程,静态变量此时会有一个系统初始值。

    3、类加载检查通过后,为新生对象在堆中分配内存,对象所需内存大小在类加载完后可完全确定。

    为对象分配内存有两种方法:

      指针碰撞 —— 如果java堆内存绝对规整,用过的内存在一边,空闲的内存都在另一边,中间放一个指针作为分界点,分配时把指针往空闲空间一端移动与对象大小相等的距离。(Serial、ParNew等带Mark-Compact标记整理

      空闲列表 —— java堆不规整,虚拟机维护一个列表,记录哪些内存块可用,分配时从列表中找到一块足够大的空间划分给对象实例,并更新列表记录。(CMS基于Mark-Sweep——标记清除

    为对象分配内存时要注意线程安全问题:

       解决对象创建时线程不安全的问题有两种方案,一种是对分配内存空间的动作进行同步处理——CAS配上失败重试;

      一种是使用TLAB让每个线程在java堆中先预留一小块内存-XX:+/-UseTLAB参数控制是否开启

    4、分配完空间后,为分配的内存空间初始化零值(不包括对象头),保证对象的实例字段在java代码中可以不附初始值直接使用。这个阶段是虚拟机对对象的初始化,成员变量此时会有一个系统初始值。

    5、对象头设置

      对象头存储“对象是哪个类的实例,如何才能找到类的元数据信息,对象哈希码、对象GC分代年龄等,是否使用偏向锁”等信息。

    6、执行<init>方法,这个阶段才把对象按程序员的意愿进行初始化。

    二、对象的内存布局

      对象是存在堆中的,那么对象的结构又是如何的呢?对象在内存中存储的布局可分为3部分:对象头、实例数据、对齐填充。

    1、对象头

    (1)对象头第一部分是“Mark Word”,以复用自身存储空间的方式存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。

      结构如下图,以第一行为例,在32位的HotSpot虚拟机中,如果对象是无锁的状态,那么这时“Mark Word”的32bit空间中的25bit就用于存对象的哈希码,4bit用于存对象分代年龄,2bit用于存锁标志位,1bit固定为0。

      

    (2)对象头的另一部分是类型指针,能通过这个指针来确定该对象是哪个类的实例,即指向方法区中类数据的指针。但不是所有虚拟机都将类型指针保留在对象数据上,结合句柄、直接指针两种方式。

    (3)如果对象是数组,对象头还要有一块记录数组长度的数据。

     2、实例数据

       对象真正存储的有效信息,包括存从父类继承下来或在子类中定义的各种类型的字段内容,这部分存储顺序会受虚拟机分配策略参数(FieldsAllocationStyle)和字段在源码中定义顺序的影响。

    3、对齐填充部分

      起占位符的作用,保证对象的大小必须是8字节的整数倍。

    三、对象的访问

      建立对象后,需要通过栈上的reference数据去定位堆中对象的具体位置,有句柄和直接指针两种方式。

    (1)句柄:若使用句柄方式,java堆中会划分出一块内存作为句柄池,reference存的是对象的句柄地址,句柄存的是实例数据与类型数据的地址。

        

    (2)直接指针:若使用这种方式reference中存的直接就是对象地址,并且对象的结构里就要考虑如何放置类型指针的相关信息。

       

    对比来说,句柄的好处是,reference中存储的是稳定的句柄地址,对象被移动时只会改变句柄中的实例数据指针,reference本身不需要修改。

           直接指针的好处是,速度快,节省了一次指针定位的时间开销,HotSpot采用的是直接指针的方式。

  • 相关阅读:
    在Linux下运行YY,WINE方式,主要注册表修改点及字体文件列表
    安卓so下,cmake编译系统,如何仅导出指定符号
    AutoHotKey脚本模板:初始化、配置、退出
    资源ID管理插件:VS6/VS.NET
    ListView控件,表格模式下,如何调整行高
    通过wscript运行的JS脚本,如何引入另一个JS文件
    64位编译器下,将指针转换成UINT32,不需要修改编译选项的编码方式
    视频帧双缓冲区的两个版本
    opencv、numpy中矩阵转置,矩阵内的固定位置相应的坐标变换
    CMake下,某些选项的后调整
  • 原文地址:https://www.cnblogs.com/zjxiang/p/9211738.html
Copyright © 2011-2022 走看看