1、对象的创建

在语言层面上,创建对象(例如克隆,反序列化)通常仅仅是一个new关键字而已。

在虚拟机中,对象(文中讨论的对象限于普通 Java 对象,不包括数组和 Class 对象等)的创建过程如下:

1.1、分配内存

空间分配的两种方式

  • 指针碰撞:当已分配空间被集中存放,已分配和未分配空间使用一个指针来标记时,分配新的空间只需要移动该指针即可,此方法为指针碰撞。适用于 GC 算法会做 Compact 的情况。
  • 空闲列表:当已分配的空间是分散存放时,虚拟机必须维护一个记录了哪些内存块是可用的列表,此为空闲列表,需要分配新空间时只需要从该列表中获取。

分配方式的选择取决于由Java堆是否规整,而Java堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。 因此,在使用 Serial、 ParNew 等带 Compact 过程的收集器时,系统采用的分配算法是指针碰撞,而使用 CMS 这种基于 Mark-Sweep 算法的收集器时,通常采用空闲列表。

解决空间分配线程安全问题的两种方式

  • CAS方式失败重试:顾名思义,遇上分配时的线程冲突时,会再次进行空间分配直至成功。实现简单直观但是效率较低
  • 空间划分:为每个线程分配单独的一块空间,该空间只用来给该线程做创建对象分配空间时使用,这单独的空间被称为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB)。当该线程的 TLAB 分配光了后,才需要同步锁定,效率较高。是否使用TLAB可以通过虚拟机参数 -XX:+/-UseTLAB 指定。

2、对象的内存布局

2.1、设置对象头

对象头包含两部分信息:

  • 运行时数据(hash码、GC分代年龄、锁状态标志、 线程持有的锁、 偏向线程ID、 偏向时间戳等),这部分数据被称为 Mark Word。
  • 类型指针,用来说明该对象是哪个类的实例。

2.2、设置对象实例数据

对象的实例数据主要是根据 JAVA 代码的编写生成的,包括父类在内的各种类型的字段,其存储顺序受虚拟机分配策略参数及代码中字段定义顺序的影响。

虚拟机安排字段的方式:

  1. 相同宽度的字段放在一起
  2. 父类的字段放在子类的前面
  3. 窄小的变量也会被安排在父类的字段空隙中(C++的内存安排规则,HotSpot VM是由C++语言编写)

2.3、填充字段

HotSpot VM要求对象的起始位置必须是8字节的整数倍,也就是说对象必须是8字节的整数倍,所以需要填充占位(这也是一句C++的规则来的)。

3、对象的访问

JAVA 程序访问对象需要通过栈上的 reference 数据操作堆上的具体对象。reference 对对象的访问方式主要为句柄和直接指针两种。

句柄访问

Java堆中将会划分出一块内存来作为句柄池,reference中存储的是对象的句柄地址,句柄中包含了对象实例数据与类型数据各自的具体地址信息。

直接指针访问

reference中存储的直接就是对象地址

句柄访问方式的好处是 reference 中存储的是稳定的句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而 reference 本身不需要修改。

直接指针访问方式的好处是速度更快,它节省了一次指针定位的时间开销。

虚拟机Sun HotSpot 使用的是直接指针访问。

深入理解JVM(4)——对象的创建和访问的更多相关文章

  1. 深入理解JVM(二)--对象的创建

    Java是一门面向对象的语言,在Java程序运行的过程中,无时无刻都会有对象被创建出来,在程序语言中,创建对象(例如克隆,反序列化)通常仅仅是一个new关键字,但是在虚拟机中是怎样的呢?本文主要了解一 ...

  2. JVM中对象的创建过程

    JVM中对象的创建过程如以下流程图中所示: 对其主要步骤进行详细阐述: 为新生对象分配内存: 内存的分配方式: 指针碰撞:假设Java堆中内存是绝对规整的,所有用过的内存放在一边,空闲的内存在另一边, ...

  3. 深入理解java虚拟机---对象的创建过程(八)

    1.对象的创建过程 由于类的加载是一个很复杂的过程,所以这里暂时略过,后面会详细讲解,默认为是已加载过的类.着重强调对象的创建过程. 注意: 最后一步的init方法是代码块和构造方法. 以上是总图,下 ...

  4. JVM(三) 对象的创建过程

    1.对象的创建过程 1.1 . 给对象分配内存 对象的内存分配有两种方式,一种是指针碰撞另外一种是空闲列表的方式,堆是否规整由我们垃圾回收器来决定的 ,如果垃圾回收带有我们的压缩算法,那么他会规整的分 ...

  5. 理解JVM之对象的生命周期

    1.对象的创建 1) 当虚拟机遇到一条new的指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载,解析和初始化过. 2) 在类加载检查通 ...

  6. Java虚拟机-对象的创建和访问

    一.对象的创建: 创建对象在java上面是很简单的,使用new关键字就可以了,但是其实在虚拟机中,java对象的创建是一个复杂的过程. 当java虚拟机遇到一个new的指令的时候,对象创建的程序正式启 ...

  7. 【Java 它 JVM】对象的创建过程

    虚拟机会new 指令: 1.检查指令的参数可在对类的符号引用的恒定饮食定位,并检查是否已装上代表这个类的符号引用.分析和初始化.假设没有.您必须运行相应的类加载过程. 2.类加载通过审查,虚拟机将分配 ...

  8. 深入理解JVM(三) -- 对象的内存布局和访问定位

    一 对象的内存布局: 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header),实例数据(Instance Data)和对齐填充(Padding). HotSpot的对 ...

  9. JVM之对象的创建简要流程

随机推荐

  1. Python编写脚本(输出三星形状的‘*’符号)

    环境:python3.* 心得:个人认为脚本非我强项,以下效果可以有更简单解决方案,纯属练习逻辑. 方案一: s=1 while s<=10: #这是决定多少列,起始为1,大循环一圈即加一,就是 ...

  2. Left Jion和where区别

    首先,新建两张表A和B,然后插入6条数据到A表,3条数据到B表.语句如下: create table A( ID ,) not null, AName ) null ) create table B( ...

  3. pycharm设置自动换行的方法

    只对当前文件有效的操作:菜单栏->View -> Active Editor -> Use Soft Wraps: 如果想对所有文件都有效,就要在setting里面进行操作:File ...

  4. LeetCode算法题-Maximum Product of Three Numbers(Java实现)

    这是悦乐书的第275次更新,第291篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第143题(顺位题号是628).给定一个整数数组,从其中找出三个数,使得乘积最大.例如: ...

  5. Interrupt中断线程注意点

    首先我们要明确,线程中断并不会使线程立即退出,而是发送一个通知,告知目标线程你该退出了,但是后面如何处理,则完全有目标线程自行决定. 这就是和stop()不一样的地方,stop执行后线程会立即终止,这 ...

  6. Kafka 0.11.0.0 实现 producer的Exactly-once 语义(英文)

    Exactly-once Semantics are Possible: Here’s How Kafka Does it I’m thrilled that we have hit an excit ...

  7. Nginx代理的几种模式

    转载自一位大佬 通常我们都知道Nginx性能很高,尤其是作为一个代理服务器,因为它用的是epoll模型,就比如Python Django Web的性能不行,我们可能就会在前端加一个nginx代理,从而 ...

  8. android开发学习 ------- 关于getSupportFragmentManager()不可用的问题

    在Android开发中,少不了Fragment的运用. 目前在实际运用中,有v-4包下支持的Fragment以及app包下的Fragment,这两个包下的FragmentManager获取方式有点区别 ...

  9. Nodejs OracleDB详细解读

    //导入oracledb模块 //基于版本@3.0.1 安装指令npm install oracledb //node访问oracleDB需要搭建访问环境,否则无法正常访问 //创建Oracle对象 ...

  10. svn冲突意思

    运行svn update更新本地内容是,发生冲突: Conflict discovered in '/home/user/test/test_web.py'. Select: (p) postpone ...