上一章主要写到了JVM中运行时数据区域各个部分的功能及其作用。上一章说到了对象是分配在堆上面的,所以接下来我们写到对象在堆内存中是如何创建、如何布局、如何访问。
1. 对象的创建
  在java程序中对象的创建很简单只需要通过new关键字就能创建一个对象,例如:String str = new String()。虽然我们看起来其实很简单,但是实际底层做的事情并不是我们表面看到的那么简单。当虚拟机遇到一个new指令时,首先将会去检查这个指令的参数是否在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化过了(单例模式只需要创建一次)。如果没有创建,那么就必须先执行相应的类加载过程。等类加载完成之后,接下来虚拟机就会给新对象分配内存,当然对象需要多大的内存空间在类加载完成之后就已经确定了。
虚拟机内存分配方式大概有两种,一种是“指针碰撞”,另一种是“空闲列表”。 “指针碰撞”是堆内存是绝对规整的,什么是绝对规整,就是所有用过的内存和没有使用的内存分开,中间放着一个指针作为分界点的指示器,那么所分配的内存就仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离。“空闲列表”的分配方式是已经使用的内存和空闲的内存相互交错在一起,虚拟机使用一个列表来记录哪些内存块可用,在分配的时候只需要找到一块足够大的空间分配给对象,然后更新这个列表的记录。选择哪一种分配方式主要取决于堆内存是否是规整的状态。
2. 对象的内存布局
  对象在内存中存储的布局可以分为三块区域:对象头、实例数据和对齐填充。
  对象头包括两部分,第一部分用于存放对象自身的运行数据,如哈希码。GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。另一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针确定这个对象是哪个类的实例。实例对象是对象真正存储的有效信息,也就是在程序中定义的各种类型字段内容。对齐填充并不是必然存在的,也没有什么特别的含义,它仅仅起着占位符的作用。
3. 对象的访问
  我们创建对象的目的是为了使用对象,上一章我们写到了运行时数据区域中各个部分的作用和功能,那么对象访问其实就会用到那些知识。对象的访问是通过栈中的引用地址(类似指针)来操作堆上的对象。目前最主流的对象访问方式主要有两种“句柄”方式和“直接指针”。
  句柄方式堆将会在堆内存中划分一块内存来作为句柄池,在栈(虚拟机栈)存放句柄地址,句柄中存放对象实例数据和类型数据各自具体的地址信息。下图为句柄访问方式访问。
    

  直接指针方式就很直接,reference中存储的就是对象的地址,通过这个地址就能很快的访问到对象及其数据。下图为直接指针方式访问。

  对比这两种访问方式都各自都自己的优势,句柄最大的优点就是reference中存储的是最稳定的句柄地址,在对象移动时只会改变句柄中的实例数据,而reference本身不需要修改。直接指针最大的优点是访问速度快。
在这里对象的创建、布局以及访问就讲解完了,希望对大家平时工作中有所帮助。既然对象是分配在堆上的,基本数据类型和引用地址是分配在栈(java虚拟机栈)上的。那么一定会出现内存空间不够用的情况,所以就会抛出OutOfMemoryError,下一节将会写到哦…..

文章作者介绍:
来自于小豹科技的李维-公司专注于软件基础研发平台,目前公司正在研发一款基于Netty的插件式的API网关-小豹API网关。 希望与对OpenAPI、微服务、API网关、Service Mesh等感兴趣的朋友多交流。 有兴趣的朋友请加QQ群244054462。

JAVA虚拟机之对象探秘的更多相关文章

  1. 深入Java虚拟机--判断对象存活状态

    程序计数器,虚拟机栈和本地方法栈 首先我们先来看下垃圾回收中不会管理到的内存区域,在Java虚拟机的运行时数据区我们可以看到,程序计数器,虚拟机栈,本地方法栈这三个地方是比较特别的.这个三个部分的特点 ...

  2. Java虚拟机学习 - 对象访问

    对象访问会涉及到Java栈.Java堆.方法区这三个内存区域. 如下面这句代码: Object objectRef = new Object(); 假设这句代码出现在方法体中,"Object ...

  3. Java虚拟机判定对象存活算法

    1.引用计数算法 描述:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器值为0的对象就是不可能再被使用的. 特点:实现简单,判定效率高. ...

  4. Java虚拟机构建对象过程小记

    Java对象的内存分布 Java对象的构建 Java程序中,新建对象,除了常见的new语句之外,还可以通过反射机制.Object.clone方法.反序列化以及Unsafe.allocateInstan ...

  5. Java 虚拟机的对象创建

    堆中存储的内容:在程序运行时,动态创建的对象. 创建对象的四种方式:new,clone(浅复制),反射,反序列化. 浅复制:只能复制当前对象本身,如果当前对象(A)引用了另外的对象(B),则引用对象( ...

  6. @Java虚拟机之对象访问

    建立对象是为了使用对象,我们的java程序需要通过栈上的reference数据来操作堆上的具体对象. 对象访问会涉及到Java栈.Java堆.方法区这三个内存区域. 如下面这句代码: Object o ...

  7. Java虚拟机学习 - 对象访问 (2)

    对象访问会涉及到Java栈.Java堆.方法区这三个内存区域. 如下面这句代码: Object objectRef = new Object(); 假设这句代码出现在方法体中,"Object ...

  8. Java虚拟机(二)-对象创建

    这一篇大致说明一下,对象在Java堆中对象分配.内存布局以及访问定位 1.对象的创建 虚拟机在遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引 ...

  9. Java虚拟机new对象

    类加载检查java虚拟机在遇到一条 new 指令时,首先会检查是否能在常量池中定位到这个类的符号引用,并且是否已被加载过.解析和初始化过.如果没有,那必须先执行类加载过程 类加载的相关知识可参考:JV ...

随机推荐

  1. Python 多线程进程高级指南(二)

    本文是如何<优雅地实现Python通用多线程/进程并行模块>的后续.因为我发现,自认为懂了一点多线程开发的皮毛,写了那么个multi_helper的玩意儿,后来才发现我靠原来就是一坨屎.自 ...

  2. bzoj 1492: [NOI2007]货币兑换Cash

    Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下 简称B券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是一个 ...

  3. python自动生成excel报表

    1.将SQL语句查询的内容,直接写入到excel报表中,以下为全部脚本.要求:此版本必须运维在windows平台,并且安装了excel程序,excel版本不限. python版本为2.7 if b 判 ...

  4. 【bird-java】bird-java概述

    bird-java是以dubbo为基础的分布式服务框架,专注于业务开发,提炼后台应用中的经典业务场景,大幅减少开发编码量. 技术选型 基础框架:spring 服务调度:dubbo web层:sprin ...

  5. 轻量级quill富文本编辑器

    因为公司产品需要在移动端编辑文本,所以发现了这个轻量级的好东西,网上也没找到比较好的案例,就自己总结了下,有兴趣的直接复制代码运行看看就知道啦! 下面是quill.js的CDN加速地址: <!- ...

  6. 自动生成getter,setter方法的插件lombok

    1.在InteiliJ IDEA上安装lombok插件,并重启 . 2.在pom.xml文件中添加依赖 <dependency>    <groupId>org.project ...

  7. jQuery实现表的编辑删除添加(增删改查)🌚

    代码 : (用到了bootstrap里面的全局css样式和组件,毕竟一把梭.

  8. 如何把Excel中的单元格等对象保存成图片

    对于Excel中的很多对象,比如单元格(Cell),图形(shape),图表(chart)等等,有时需要将它们保存成一张图片.就像截图一样. 最近做一个Excel相关的项目,项目中遇到一个很变态的需求 ...

  9. Benchmark Test On Android Devices

    一.Android设备上的Benckmark测试概述 同PC相比,在Android设备上的性能测试还没有一个公认的标准.也没有PC上那么多的测试程序集.但我们可以通过一些工具所得到的信息更好的了解设备 ...

  10. Oracle相关知识做个总结

    一.创建用户: 以系统管理员登陆,右键点击Uers进行新建, 一般:默认空间选择USERS,临时表空间选择TEMP,概要文件选择DEFAULT. 对象权限:不做操作. 角色权限:1.connect 2 ...