这篇文章主要讲解了“Java对象存储内存布局的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java对象存储内存布局的方法是什么”吧!
众所周知,Java是一门面向对象的语言,那么一个对象在内存中都包含什么东西呢,首先,对象大部分是存储在堆上的(逃逸除外 )。
那么对象存储在堆中主要分为三个部分
对象头、对象实例数据、对齐补充(数组会多一个数组长度)
对象头:
mark word: 存储对象的hashCode、锁信息(锁升级)或分代年龄或GC标志等信息
类型指针: 存储指向对象所属类(元数据中class文件)的指针,JVM通过这个确定这个对象属于哪个类
对象实例数据:
new出的对象信息,存放类的属性数据信息,包括父类的属性信息;
对齐补充
数组对象会多对齐填充
JVM要求对象占用的空间必须是8 的倍数,方便内存分配(以字节为最小单位分配),因此这部分就是用于填满不够的空间凑数用的。
主流的访问方式主要有句柄与直接指针
句柄:
Java堆中划分出一块内存作为句柄池,栈中的reference中存储的事对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自具体的地址信息
直接指针:
java堆中对象的内存布局必须考虑如何防止访问类型数据的相关信息,reference中存储的直接是对象地址。
直接指针访问对象不需要多一次间接访问开销,而句柄方便在对象地址发生改变时(垃圾回收会移动对象地址)只需要改变句柄中的指针引用本身不需要改变。
虚拟机遇到new指令时,先去检查指定的类是否被加载、验证、准备(为类中的所有静态变量分配内存空间,并为其设置一个初始值 ) 、解析、初始化过。
类检查后虚拟机为新对象分配内存
如何保证并发情况分配堆内存安全
虚拟机采用CAS配上失败重试保证原子性
把内存分配交给线程,在创建线程时分配空间,把分配内存的任务交给线程支配。通过TLAB(Thread local Allocation Buffer)开启
分配完内存后设置对象头,如哪个类的实例、hashcode、类的元数据信息指针(方法区)
执⾏ init ⽅法(内核方法),初始化成员变量,执⾏实例化代码块,调⽤类的构造⽅法,并把堆内对象的⾸地址赋 值给引⽤变量。
CAS 加失败重试保证更新原⼦性。
把内存分配按线程划分在不同空间,即每个线程在 Java 堆中预先分配⼀⼩块内存,叫做本地线程分配缓冲 TLAB,哪个线程要分配内存就在对应的 TLAB 分配,TLAB ⽤完了再进⾏同步。
父类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行
子类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行
父类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行
父类构造方法
子类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行
子类构造方法
感谢各位的阅读,以上就是“Java对象存储内存布局的方法是什么”的内容了,经过本文的学习后,相信大家对Java对象存储内存布局的方法是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。