基于 Hostpot 虚拟机的 Java 对象揭秘(上)

简介: 基于 Hostpot 虚拟机的 Java 对象揭秘

对象的创建


Java 是一门面向对象的编程语言,创建对象通常只是通过 new关键字创建。


对象创建过程


当虚拟机遇到一个字节码 new指令的时候,首先去检查这个指令的参数是否能够在常量池中定位到一个类的符号引用。并且检查这个符号引用代表的类是否被虚拟机类加载器加载。如果没有,必须先执行类加载的流程。


image.png


在类的检查通过过后,接下来虚拟机就会为新生成对象分配内存。对象所需要的内存大小在类加载的时候决定。(对象内存分配后面将有独立的一小段讲解)。


内存分配完成后,虚拟机会将这块分配到的内存空间(不包括对象头)都初始化为零值,就是将这块内存空间进清理和初始化。


接下来虚拟机还需要进行对象进行初始化设置,比如元数据(对象是那个类的实例)、对象的哈希编码、对象的 GC 分代年龄、偏向锁状态等信息这些信息都用于存放到对象头(Object Header)中。


完成上述流程,其实已经完成了虚拟机中内存的创建,但是我们在 Java 执行 new创建对象的角度才刚刚开始,我们还需要调用构造方法初始化对象(可能还需要在此前后调用父类的构造方法、初始化块等)


进行 Java 对象的初始化。即在 .class 的角度是调用 <init>()方法。如果构造方法中还有调用别的方法,那么别的方法也会被执行,当构造方法内的所有关联的方法都执行完毕后,才真正算是完成了 Java 对象的创建。


对象内存分配


对象内存分配过程如下图所示:


image.png


为对象分配空间的任务实质上是从 Jvm 的内存区域中,指定一块确定大小的内存快给 Java 对象。(默认是在堆上分配)。


指针碰撞


假设 Java 堆中内存是绝对规整的,所有使用过的内存都被放在一边,没有使用过的内存放在了另外一边。中间放着一个指针用来表示他们的分界点。那所分配的内存仅仅是把那个指针向空闲的方向挪动一段与Java对象大小相等的距离,这种分配方式叫做 “指针碰撞”(Dump The Pointer)


image.png


空闲列表


但是如果 Java 堆中内存并不是规整的,已经使用的内存块,和空闲的内存块相互交错在一起,那就没有办法简单的进行指针碰撞了,虚拟机必须维护一个可用内存区域列表。 记录那些内存块是可以使用的。在对象内存分配的时候就从列表中去找到一块足够大的内存空间划分给实例对象,并且更新列表上的记录。这种分配方式叫做 “空闲列表”(Free List).


image.png


内存分配方式选择


什么时候使用指针碰撞,什么时候才用空闲列表?选择哪一种分配方式是由 Java 堆是否规整决定的,而 Java 堆是否规整又是由所采用的垃圾回收器是否有空间整理(Compact)的能力决定。


  • 当使用 Serial 、ParNew 等带指针压缩整理过程的收集器时,系统采用的分配算法是指针碰撞,既简单,又高效。


  • 当采用 CMS 基于清除(Sweep)算法的收集器时,理论上只能采用复杂的空闲列表来分配内存。


并发内存分配方案


对象频繁分配的过程中,即使只修改一个指针所指向的位置,但是在并发的情况下也不是线程安全的,可能出现正在给 A 对象分配内存,指针还没有来得及修改,对象 B 又同时使用来原来的指针进行内分配的情况。解决这个问题有两种可选的方案:


  • 一种是对内存分配空间的动作进行同步处理-实际上虚拟机是采用CAS  + 失败重试的方式来保证更新操作的原子性。


  • 另外一种就是把内存分配的动作按照线程划分在不同的空间中进行,即每个线程在 Java 堆中预先分配一小块内存,称为本地线程分配缓冲(Thred Local Allocation Buffer, TLAB), 那个线程要分配内存,就在那个线程分配内存,就在那个线程的本地缓冲中分配,只有本地缓冲用完了,分配新的缓冲区时才需要同步锁定,虚拟机是否使用 TLAB,可以通过 -XX:+/-UseTLAB参数设置。


对象的内存布局


在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。下图是普通对象实例与数组对象实例的数据结构:


image.png


相关文章
|
27天前
|
Java
java8中List对象转另一个List对象
java8中List对象转另一个List对象
37 0
|
27天前
|
缓存 Java C#
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(一)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
76 0
|
1天前
|
设计模式 JavaScript Java
[设计模式Java实现附plantuml源码~行为型] 对象状态及其转换——状态模式
[设计模式Java实现附plantuml源码~行为型] 对象状态及其转换——状态模式
|
3天前
|
Java
Java基础之对象的引用
Java基础之对象的引用
5 0
|
7天前
|
Java
Java中如何克隆一个对象?
【4月更文挑战第13天】
15 0
|
9天前
|
Java API 数据库
深入解析:使用JPA进行Java对象关系映射的实践与应用
【4月更文挑战第17天】Java Persistence API (JPA) 是Java EE中的ORM规范,简化数据库操作,让开发者以面向对象方式处理数据,提高效率和代码可读性。它定义了Java对象与数据库表的映射,通过@Entity等注解标记实体类,如User类映射到users表。JPA提供持久化上下文和EntityManager,管理对象生命周期,支持Criteria API和JPQL进行数据库查询。同时,JPA包含事务管理功能,保证数据一致性。使用JPA能降低开发复杂性,但需根据项目需求灵活应用,结合框架如Spring Data JPA,进一步提升开发便捷性。
|
13天前
|
存储 Java 编译器
对象的交响曲:深入理解Java面向对象的绝妙之处
对象的交响曲:深入理解Java面向对象的绝妙之处
46 0
对象的交响曲:深入理解Java面向对象的绝妙之处
|
18天前
|
Java
在Java中,多态性允许不同类的对象对同一消息做出响应
【4月更文挑战第7天】在Java中,多态性允许不同类的对象对同一消息做出响应
17 2
|
27天前
|
Java
Java常用封装Base对象
Java常用封装Base对象
8 0
|
2月前
|
虚拟化
vmware克隆虚拟机后没有ip地址的问题
解决vmware克隆虚拟机后没有内网ip的问题