概述:

  上一篇文章,介绍了虚拟机类加载的过程,那么类加载好之后,虚拟机下一步该干什么呢。我们知道java是面向对象的编程语言,所以对象可以说是java'的灵魂,这篇文章我们就来介绍

虚拟机是如何创建对象、对象内存分配以及对象是如何使用的(访问定位)。由于各个虚拟机的实现不尽相同,所以这里我们以最常用的HotSpot虚拟机为例来介绍。

对象的创建:

  对象在虚拟机中创建的步骤如下:

  1. 当虚拟机遇到一条字节码new指令时,首先会去检查这个类是否被加载、解析和初始化,如果没有,则执行类加载(类加载步骤这里就不介绍了,请查看JVM(三))。
  2. 类加载检查通过后,接下来虚拟机将在堆中为新生对象分配和对象同等大小的内存。
  3. 内存分配完之后,虚拟机会将分配到的内存空间(不包括对象头)都初始化为零值,保证了对象的实例字段有初始值,使得不赋值也可以使用,只是值为零而已(注意,如果是引用对象则为null)。
  4. 接下来,java虚拟机还要对对象进行必要的设置,比如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。
  5. 执行Class文件中<init>()方法,即构造函数,这样一个真正可用的对象才算完全构建完成。

对象的内存布局:

  在HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:对象头、实例数据和对其填充。

对象头:

  HotSpot虚拟机对象的对象头部分包括两类信息:

  1. 第一类是用于存储对象自身的运行数据,如何哈希码(hashcode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,官方称它为"Mark Word"。
  2. 对象头的另外一部分是类型指针,即对象指向它的类型元数据指针,java虚拟机通过指针来确定该对象是哪个类型的实例。如果是数组对象,在对象头中还有一块用于记录数组长度的数据。

实例数据:

  顾名思义,实例数据部分存储的就是实例对象的相关信息了,即我们在程序代码里面所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的字段都必须记录起来。

对齐填充:

  对象的第三部分是对齐填充,这并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。由于HotSpot虚拟机的自动内存管理系统要求对象的起始地址必须是8字节的整数倍,所以

不足8的整数倍就需要补齐。

对象的访问定位:

  创建对象自然是为了后续使用该对象,java虚拟机规范规定java程序通过虚拟机栈的reference来操作堆上的具体对象,各个虚拟机实现的访问方式也不尽相同,主流的访问方式主要使用句柄和直接指针两种,

我们先来看通过句柄的方式访问,如下图:

  通过句柄访问,java堆中会将划分出一块内存来作句柄池,reference中存储的就是对象的句柄地址,句柄中包含了对象实例数据以及类型数据的地址信息。而指针访问的话,

reference中存储的直接就是对象地址,对象实例中同时还需要存指向对象类型数据的指针。如下图所示:

  这两种对象访问方法各有优势,直接指针访问方式,虽然访问访问速度快,但是垃圾回收的效率没有句柄池的效率高。我们常用的HotSpot是使用的直接指针的方式访问对象。

JVM(四)-虚拟机对象的更多相关文章

  1. 深入了解java虚拟机(JVM) 第四章 对象的创建

    一.对象的创建过程 对象的创建过程大致可以分为六步,其中对象的分配尤为重要: 二.对象分配内存 一般来说对象分配内存有两种方式: 第一种是指针碰撞,这是一种比较理想的方式:如果Java堆是绝对规整的: ...

  2. 自制Java虚拟机(四)-对象、new、invokespecial

    自制Java虚拟机(四)-对象.new.invokespecial 一.对象的表示 刚开始学Java的时候,图书馆各种教程,书名往往都是“Java面向对象高级编程”,通常作者都会与C++做个比较,列出 ...

  3. 深入理解JVM(③)——之HotSpot虚拟机对象探秘

    前言 上篇文章介绍了Java虚拟机的运行时数据区域,大致明白了Java虚拟机内存模型的概况,下面就基于实用优先的原则,以最常用的虚拟机HotSpot和最常用的内存区域Java堆为例,升入探讨一下Hot ...

  4. JVM(四):深入分析Java字节码-下

    JVM(四):深入分析Java字节码-下 在上文中,我们讲解了 Class 文件中的文件标识,常量池等内容.在本文中,我们就详细说一下剩下的指令集内容,阐述其分别代表了什么含义,以及 JVM 团队这样 ...

  5. JVM的艺术-对象创建与内存分配机制深度剖析

    JVM的艺术-对象创建与内存分配机制深度剖析 引言 本章将介绍jvm的对象创建与内存分配.彻底带你了解jvm的创建过程以及内存分配的原理和区域,以及包含的内容. 对象的创建 类加载的过程 固定的类加载 ...

  6. 99.9%的Java程序员都说不清的问题:JVM中的对象内存布局?

    本文转载自公众号:石彬的架构笔记,阅读大约需要8分钟. 作者:李瑞杰 目前就职于阿里巴巴,资深 JVM 研究人员 在 Java 程序中,我们拥有多种新建对象的方式.除了最为常见的 new 语句之外,我 ...

  7. java四种对象引用类型

    java四种对象引用类型 对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序 ...

  8. JVM常用虚拟机命令汇总

    title: JVM常用虚拟机命令汇总 comments: false date: 2019-07-22 11:45:33 description: 总结一下常用的JVM虚拟机启动命令. catego ...

  9. JVM 堆中对象分配、布局和访问

    本文摘自深入理解 Java 虚拟机第三版 对象的创建 Java 是一门面向对象的语言,Java 程序运行过程中无时无刻都有对象被创建出来.从语言层面看,创建对象只是一个 new 关键字而已,而在虚拟机 ...

随机推荐

  1. Bash echo输出带颜色和背景的文本

    Bash echo输出带颜色和背景的文本 1.先上效果图 2.bash代码 #!/bin/bash #************************************************* ...

  2. 838. Push Dominoes —— weekly contest 85

    Push Dominoes There are N dominoes in a line, and we place each domino vertically upright. In the be ...

  3. 《Web接口开发与自动化测试》学习笔记(三)

    一.认证系统 使用django本身自带的认证系统 1.登录admin后台 1. 先建立一个管理员用户: > python manage.py creatsuperuser 输入用户名.邮箱和密码 ...

  4. [阿里DIN] 从模型源码梳理TensorFlow的乘法相关概念

    [阿里DIN] 从模型源码梳理TensorFlow的乘法相关概念 目录 [阿里DIN] 从模型源码梳理TensorFlow的乘法相关概念 0x00 摘要 0x01 矩阵乘积 1.1 matmul pr ...

  5. ExecutorService的invokeAny方法注意

    package com.msxf.datasource.thirdpart.service.extface; import java.util.HashSet; import java.util.Li ...

  6. linx 内核 并发与同步 1

    内核并发来源: 1.硬件中断和异常:中断服务程序和被中断的进程可能发生并发访问资源 2.软中断和tasklet,软中断和taklet随时都可能倍调度执行,从而打断当前正在执行 进程的上下文. 3.内核 ...

  7. python 迭代器(转)

    迭代器 迭代器是在python2.2中被加入的,它为类序列对象提供了一个类序列的接口.有了迭代器可以迭代一个不是序列的对象,因为他表现出了序列的行为.当在python中使用for循环迭代一个对象时,调 ...

  8. java1.8安装及环境变量配置

    一.前言 虽然jdk1.9版本已经问世,但是许多其他的配套设施并不一定支持jdk1.9版本,所以这里仅带领你配置jdk1.8.而jdk1.9的操作也几乎是相同的. 本教程适用于windows10 64 ...

  9. 调整PG分多次调整和一次到位的迁移差别分析

    前言 这个问题来源于我们研发的一个问题,在进行pg调整的时候,是一次调整到位好,还是分多次调整比较好,分多次调整的时候会不会出现某个pg反复挪动的问题,造成整体迁移量大于一次调整的 最近自己的项目上也 ...

  10. Windows查找JDK的路径

    第一步:确定是否安装JDK 在控制台输入: java -version 此时说明你电脑安装了JDK. 第二步:查找路径 然后在控制台输入: java -verbose 输出结果: 最后两行就是相应的j ...