几乎所有对象都是在堆中分配内存的,这次来讲讲java的对象。

对象的创建主要分为以下几步:

首先,查看类是否装载。当JVM读取到new指令的时候,会拿着符号描述去方法区寻找它所属的类,如果未查找到,则需要先对类进行加载解析初始化;

然后,为对象分配空间。主要涉及两种方式,第一种是指针碰撞法,顾名思义,两个指针挪动,为新来的对象“挪”空间,前提是配合相应的GC算法使堆空间时刻保持连续,同时,如果是多线程还需要考虑同步问题,可以使用CAS或TLAB的方式;第二种是空闲列表法,如果堆空间不连续的话可以采用此方法,每次GC之后把可利用的空间写入到一个列表,通过维护这个列表来得知在哪里给对象分配内存。

分配完内存之后,需要给对象的属性设置零值(不包含对象头的区域),即初始值,如果此时访问对象属性的话得到的将是一个零值。

接下来设置对象头信息,包括对象哈希码,类的地址,对象的GC年龄分代信息,锁状态等。

最后一步就是执行<init>方法,为对象赋值。


对象的大小

对于一个新建的无任何属性的空的Object对象,它的大小为8byte,它的引用变量前面说过,为4byte,因此创建一个空的Object对象需要占用内存12byte;如果建立一个有属性的对象需要多大空间呢?我们来分析一下

class hello{

int a;

boolean b;

Object c;

}

如果要创建这样一个对象,我们知道所有的类都需要继承Object类的,因此首先需要一个8byte的空壳对象,然后int属性占4byte,boolean属性占1byte,引用变量属性占4byte(注意c仅仅是一个引用),占用17字节,而JVM规定,对象空间占用必须为8byte的整数倍,因此需要凑整,也就是这个对象在堆中需要占用24字节大小。

这里还要说一下基本类型的包装类型的对象大小,对于这类对象,即使声明一个空对象,也至少要占用内存为12byte,这还只是个空对象,而且还要凑整,所以需要16字节,这已经是基本类型的2倍以上了,因此我们平时尽量不要使用包装类型的对象,当然,jdk5之后JVM会自动拆箱装箱,对包装类型的内存占用空间也有了一定的优化。


对象头

因为之前在学习锁优化的时候提到了Mark Word,所以这次又着重看了一下这里。对象头是一个无固定格式的,包含对象信息的一段序列。对象头的信息主要分两部分存放

第一块用来存储运行时所需要的信息,叫Mark Word,用来存放如哈希码,GC年龄分代,锁状态标志,偏向线程ID等,对于32位和64位系统,在未开启压缩指针下这部分分别为固定大小32位和64位。在未加锁32位系统下,MarkWord中有25位用来存放对象的哈希码,4bit存放对象的年龄分代信息,2bit存放锁标识位,1bit固定为0;

第二块是一个指向它所属的类的一个类型指针。

对于普通对象,JVM可以通过这个指针很轻易的找到它所属的类信息以及对象大小,但是如果是一个数组对象,通过前面所说的信息还是无法确定这个数组的大小,甚至追溯到数组对象的元数据,因此,对于数组对象,对象头信息还需要一条记录数组长度的数据。


对象的访问定位

如果想通过栈上的reference数据来访问操作对象,有两种方式,第一种是直接指针访问,这是Hotpot使用的访问方式,在引用类型中直接记录下对象的地址,速度快,但是如果频繁GC导致对象在堆中的位置频繁移动,那么该地址每次都需要修改,可能会带来一些性能问题;第二种是句柄访问,即在堆区划分出来一块内存来作为句柄池,栈中的引用类型记录对象的句柄地址,句柄地址中记录对象的实际位置,这样每次移动对象只需要维护句柄池即可,栈区无需修改,相对会稳定一些。总之,两种方式各有优点。

JVM之对象的更多相关文章

  1. JVM中对象的创建过程

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

  2. JVM中对象的回收过程

      当我们的程序开启运行之后就,就会在我们的java堆中不断的产生新的对象,而这是需要占用我们的存储空间的,因为创建一个新的对象需要分配对应的内存空间,显然我的内存空间是固定有限的,所以我们需要对没有 ...

  3. Java虚拟机笔记(五):JVM中对象的分代

    为什么要分代 为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用, ...

  4. jvm回收对象

    jvm在判断对象死亡之前需要判断对象是否可到达,方法有引用计数算法和可达性分析算法,jvm采用的是后者.首先来了解一下这两种算法. 引用计数算法: 算法定义 为每个对象增加一个字段记录被引用的次数,并 ...

  5. JVM——深入分析对象的内存布局

    概述 一个对象本身的内在结构需要一种描述方式,这个描述信息是以字节码的方法存储在方法区中的.Class本身就是一个对象,都以KB为单位,如果new Integer()为了表示一个数据就占用KB级别的内 ...

  6. JVM与对象初始化

    一个对象从无到有的过程 A a = new A() 1.JVM遇到new指令就会去堆内存分配一块内存空间,内存的大小在编译期间就可以确定 2.接着调用A的构造函数,这里构造的时候会沿着继承树逆流而上, ...

  7. JVM之对象分配:栈上分配 & TLAB分配

    1. Java对象分配流程 2. 栈上分配 2.1 本质:Java虚拟机提供的一项优化技术 2.2 基本思想: 将线程私有的对象打散分配在栈上 2.3 优点: 2.3.1 可以在函数调用结束后自行销毁 ...

  8. JVM(3)对象A和B循环引用,最后会不会不被GC回收?-------关于Java的GC机制

    ①首先说一下,GC里边在JVM其中是使用的ROOT算法,ROOT算法,什么称作为ROOT呢,就是说类的静态成员,静态成员就是static修饰的那种,是"根"的一个,根还包含方法中的 ...

  9. @JVM中对象的引用类型

    JVM中有四种引用类型:强引用.软引用.弱引用.虚引用   强引用(Stong Reference):是指在程序代码中普遍存在的,类似:Object obj = new Object()这类的引用,只 ...

  10. JVM(二) 对象存活判断和垃圾回收算法

    对象的创建 概述 下面简要介绍创建对象的几个重要步骤 : 检查能否在常量池定位到一个类的符号引用,并检查这个符号代表的类是否已被加载,解析和初始化过.如果没有则执行类加载的操作.(即是说对象的引用放在 ...

随机推荐

  1. C# POST 表单发送文件

    表单提交协议规定:要先将 HTTP 要求的 Content-Type 设为 multipart/form-data,而且要设定一个 boundary 参数,这个参数是由应用程序自行产生,它会用来识别每 ...

  2. vue4——把输入框的内容添加到页面(简单留言板)

    文章地址:https://www.cnblogs.com/sandraryan/ vue最最最简单的demo(记得引入) 实例化一个vue,绑定#app的元素,要渲染的数组arr作为data. 把ar ...

  3. Python--day72--Cookie和Session内容回顾

    1. Cookie是什么 保存在浏览器端的键值对 为什么要有Cookie? 因为HTTP请求是无状态的 Cookie的原理? 服务端可以在返回响应的时候 做手脚 在浏览器上写入键值对(Cookie) ...

  4. H3C PPP MP简介

  5. jekyll 添加 Valine 评论

    本文告诉大家如何在自己搭建的静态博客添加 Valine 评论.在这前,我基本都是使用 多说,但是多说gg啦,所以就在找一个可以替换的评论 本来 Disqus是很好的,但是在国内很难打开,所以我就需要一 ...

  6. 常用mime.types

    以下是从nginx配置文件mime.types中提取出的最常用的文件格式, 整理了下, 方便查看 类型 文件格式 default_type application/octet-stream - tex ...

  7. 2019-8-31-C#-await-高级用法

    title author date CreateTime categories C# await 高级用法 lindexi 2019-08-31 16:55:58 +0800 2018-2-13 17 ...

  8. 土旦:移动端 Vue+Vant 的Uploader 实现 :上传、压缩、旋转图片

    面向百度开发 html <van-uploader :after-read="onRead" accept="image/*"> <img s ...

  9. Blazor 服务端组件 Render, RenderFragment ,RenderTreeBuilder, CascadingValue/CascadingParameter

    一.组件 支撑Blazor的是微软的两大成熟技术,Razor模板和SignalR,两者的交汇点就是组件.通常,我们从ComponentBase派生的类型,或者创建的.razor 文件,就可以称作组件. ...

  10. VIM 用正则表达式,非贪婪匹配,匹配竖杠,竖线, 匹配中文,中文正则,倒数第二列, 匹配任意一个字符 :

    VIM 用正则表达式 批量替换文本,多行删除,复制,移动 在VIM中 用正则表达式 批量替换文本,多行删除,复制,移动 :n1,n2 m n3     移动n1-n2行(包括n1,n2)到n3行之下: ...