HotSpot Java对象创建,内存布局以及访问方式

内存中对象的创建、对象的结构以及访问方式。

一、对象的创建

在语言层面上,对象的创建只不过是一个new关键字而已,那么在虚拟机中又是一个怎样的过程呢?

(一)判断类是否加载。虚拟机遇到一条new指令的时候,首先会检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号代表的类是否被加载、解析并初始化。如果没有完成这个过程,则必须执行相应类的加载。

(二)在堆上为对象分配空间。对象需要的空间大小在类加载完成后便能确定。之后便是在堆上为该对象分配固定大小的空间。分配的方式也有两种:

i. 第一种如果使用Serial、ParNew等带Compact过程的收集器的时候,Java内存中的堆都是规整的,只需把作为使用和未使用空间的分界点的指针移动一段距离就可以了。

ii. 第二种如果使用CMS这种基于Mark-Sweep算法的收集器的时候,Java内存并不是规整的,虚拟机就要维护了一个列表来记录内存的使用情况,这种方式叫做“空闲列表”的方式。

虚拟机为对象分配空间是非常频繁的,如果同时为多个线程分配对象,就涉及到并发安全控制了。一般有两个解决方案:

(1)第一种是对分配内存空间动作进行同步–使用CAS配上失败重试的方式保证更新操作的原子性。

(2)第二种是把内存分配的动作分配在不同的空间中进行,既每个线程在Java堆中预先分配一小块内存,称之为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB)。哪个线程要分配内存,就在哪个线程的TLAB上分配。只有TLAB使用完并需要分配新的TLAB的时候才需要同步锁定。

(三)初始化内存空间。内存分配完成之后,虚拟机会将分配空间内都初始化为零值(不包括对象头),如果使用TLAB分配,这一过程也可以提前至TLAB分配时进行。

(四)设置对象的对象头。接下来虚拟机要设置对象的对象头。包括对象的哈希码、类元素信息、GC分代年龄等。这些信息都放置在对象头中。

(五)执行**方法**,初始化对象内成员。

执行完这五步,一个对象才算是真正产生。

二、对象的内存布局

内存中,对象存储布局可分为三部分:对象头(Header),示例数据(Instance Data)和对齐填充(Padding)。

i. 对象头:包括两部分信息。第一部分用于存储对象自身的运行时数据,如哈希码,GC分代年龄、锁状态、线程持有锁、等等。这部分数据的长度在32为或64位,官方称之为“Mark Word”。对象头的另一部分是类型指针,即对象指向它的类元素的指针,通过这个指针来确定这个对象时那个类的实例。(如果Java对象时一个数组,则对象头还必须有一块用于记录数组长度的数据。因为Java数组元数据中没有数组大小的记录)

ii. 实例数据:这部分是真正用来存储对象有效信息的地方。

iii. 对齐填充:这部分并不是必需存在的,只是起着占位符的作用。因为HotSpot虚拟机要求对象起始地址必须是8字节的倍数。

三、 对象的访问方式

我们可以通过使用栈上的reference数据来操作堆上的具体对象。有两种方式来访问具体对象:句柄和直接指针。

句柄:Java堆中划分出一个句柄池,专门用来存放对象的实例地址和类型地址。而栈中的reference只是该句柄池中某一句柄的地址。好处是当进行垃圾回收并被移动后,对象地址改变而reference的数据不用改变。

直接指针:reference直接指向某一对象的地址。好处便是速度快,节省了一次定位的时间开销。

更多技术资讯可关注:itheimaGZ获取

原文地址:https://www.cnblogs.com/zhuxiaopijingjing/p/12256512.html

时间: 2024-08-21 15:47:01

HotSpot Java对象创建,内存布局以及访问方式的相关文章

深入理解java虚拟机(二)HotSpot Java对象创建,内存布局以及访问方式

内存中对象的创建.对象的结构以及访问方式. 一.对象的创建 在语言层面上,对象的创建只不过是一个new关键字而已,那么在虚拟机中又是一个怎样的过程呢? (一)判断类是否加载.虚拟机遇到一条new指令的时候,首先会检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号代表的类是否被加载.解析并初始化.如果没有完成这个过程,则必须执行相应类的加载. (二)在堆上为对象分配空间.对象需要的空间大小在类加载完成后便能确定.之后便是在堆上为该对象分配固定大小的空间.分配的方式也有两种:

深度理解java虚拟机读书笔记(二)HotSpot Java对象创建,内存布局以及访问方式

内存中对象的创建.对象的结构以及访问方式. 一.对象的创建 在语言层面上,对象的创建只不过是一个new关键字而已,那么在虚拟机中又是一个怎样的过程呢? (一)判断类是否加载.虚拟机遇到一条new指令的时候,首先会检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号代表的类是否被加载.解析并初始化.如果没有完成这个过程,则必须执行相应类的加载. (二)在堆上为对象分配空间.对象需要的空间大小在类加载完成后便能确定.之后便是在堆上为该对象分配固定大小的空间.分配的方式也有两种:

Java对象的内存布局以及对象的访问定位

先来看看Java对象在内存中的布局 一 Java对象的内存布局 在HotSpot虚拟机中,对象在内存中的布局分为3个区域 对象头(Header) Mark Word(在32bit和64bit虚拟机上长度分别为32bit和64bit)存储对象自身的运行时数据,包括哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时 间戳等 类型指针 即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例.但是并不是所有类型虚拟机实现都必须在对象数据上保留类型指针,如果对象是一

Java对象的内存布局

Java对象的内存布局:对象头(Header),实例数据(Instance Data),对齐填充(Padding):另外:不同的环境结果可能有差异,我所在的环境是HotSpot虚拟机,64位Windows. 对象头 对象头在32位系统上占用8bytes,64位系统上占用16bytes. System.out.println("sizeOf(new Object()) = " + sizeOf(new Object())); sizeOf(new Object()) = 16 实例数据

java对象的内存布局(一):计算java对象占用的内存空间以及java object layout工具的使用

最近在学习java对象内存布局方面的一些知识,主要是想知道一个java对象到底占用多少内存空间,以及java对象在内存中到底是什么样子的.c/c++中的sizeof运算符能够方便地告诉我们一个变量占用的内存空间,但是在java中却没有直接提供这种机制.如果想获取java对象占用的内存大小,可以利用java的Instrumentation机制.java.lang.instrument.Instrumentation这个接口提供了getObjectSize(Object objectToSize),

Java对象创建的过程及对象的内存布局与访问定位

这里以HotSpot为例,且所说的对象指普通的Java对象,不包括数组和Class对象等. 1.对象创建的过程 类加载.解析.初始化:虚拟机遇到new时先检查此指令的参数是否能在常量池中找到类的符号引用,并检查符号引用代表的类是否被加载.解析.初始化,若没有则先进行类加载. 对象内存分配:类加载检查通过后,虚拟机为新生对象分配内存,对象所需内存大小在类加载完成后便可完全确定.分配内存的任务等同于从堆中分出一块确定大小的内存. 根据内存是否规整(即用的放一边,空闲的放另一边,是否如此与所使用的垃圾

Java对象的内存布局以及对象所需内存大小计算详解

1. 内存布局 在HotSpot虚拟机中,对象的内存布局可以分为三部分:对象头(Header). 实例数据(Instance Data)和对齐填充(Padding). 1) 对象头(Header): 对象头又可以分为两部分: 第一部分用来存储对象自身的运行时基本数据信息.如哈希码.GC分代年龄.锁状态标示.线程持有的锁等.这部分数据的长度在32bit和64bit虚拟机上分别为32bit和64bit.官方称呼是"Mark Word". 第二部分是类型指针,或者说指向类的元数据信息的引用.

java对象的内存布局(二):利用sun.misc.Unsafe获取类字段的偏移地址和读取字段的值

在上一篇文章中.我们列出了计算java对象大小的几个结论以及jol工具的使用,jol工具的源代码有兴趣的能够去看下.如今我们利用JDK中的sun.misc.Unsafe来计算下字段的偏移地址,一则验证下之前文章中的结论,再则跟jol输出结果对照下.怎样获取sun.misc.Unsafe对象.能够參考这篇文章. public class VO { public int a = 0; public long b = 0; public static String c= "123"; pub

new Java对象占用内存分析

最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好:http://yueyemaitian.iteye.com/blog/2033046,里面提供的这个类也非常实用: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35