美文网首页
Java中对象的内存布局

Java中对象的内存布局

作者: 小丸子的呆地 | 来源:发表于2021-07-12 11:29 被阅读0次

所谓内存布局,指的是一个对象在内存中的组成。通常由三部分组成

  1. 对象头(包含MarkWord、Klass Pointer、数组长度)
  2. 对象实例数据
  3. 对齐(一个完整对象需要为8个字节的倍数),可能没有
image.png

所以在开启指针压缩的条件下,一个空Object对象为16个字节:

8字节 MarkWord
4字节 元数据指针
4字节 对齐

一个Long对象为24个字节,Long对象的成员变量只有一个long,而long是占有8个字节的:

8字节 MarkWord
4字节 元数据指针
8字节 long
4字节 对齐

对象头

MarkWord

MarkWord中包含了很多信息,比如锁信息、hashcode、gc信息、线程信息,在对象不同的阶段存储不同的信息。 markword-64.png
  • Hashcode
    在无锁状态下存储,开始时没有的,调用过对象的一次hashcode()方法之后,会将hashcode存储到对象头。
  • 分代年龄
    在GC中,对象由年轻代晋升老年的的判断标准之一就是这个分代年龄,因为这里只使用了4位进行存储,所以津国这个分代年龄可以调整,但是最大值也只能是15。
  • 偏向锁信息
    现在对象创建默认是偏向锁状态,可以通过参数配置。
  • 锁标志位
    受synconized关键字影响,由synconized修饰的对象,会被当成一把锁,在锁竞争过程中会通过锁标志位来标记当前的锁状态。
    关于synconized关键字,参看另一篇文章:https://www.jianshu.com/p/be8ccd456b32

元数据指针

我们知道JVM加载一个类之后,解析出这个类的信息放入方法区,并会生成一个class对象放在了堆中。元数据指针指向的是方法区内部的类信息。

类加载机制概念

Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的加载机制。

Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允许用户借由这个Class相关的元信息对象间接调用Class对象的功能,这里就是我们经常能见到的Class类。

  1. 装载:查找和导入Class文件;
  2. 链接:把类的二进制数据合并到JRE中;
    (a)校验:检查载入Class文件数据的正确性;
    (b)准备:给类的静态变量分配存储空间;
    (c)解析:将符号引用转成直接引用;
  3. 初始化:对类的静态变量,静态代码块执行初始化操作
  4. 使用
  5. 卸载

注意第一步的装载:
类的装载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。

方法区

方法区是JVM规范中,规划的一块区域。hospot对其实现在1.8之前是永久代,1.8之后是元空间,1.7是过渡阶段。

使用元空间的优点
  1. 不会出现“java.lang.OutOfMemoryError: PremGen space”异常
  2. 字符串常量池迁移到堆中,避免溢出
  3. 永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
  4. 通过类加载器来控制垃圾回收。
元空间Metaspace

分为两个部分Klass Metaspace 和NoKlass Metaspace。

  • Klass Metaspace
  1. Klass Metaspace就是用来存klass的,就是class文件在jvm里的运行时数据结构(不过我们看到的类似A.class其实是存在heap里的,是java.lang.Class的对象实例)。
  2. 这部分默认放在Compressed Class Pointer Space中,是一块连续的内存区域,紧接着Heap,和之前的perm一样。通过-XX:CompressedClassSpaceSize来控制这块内存的大小,默认是1G。
  3. Compressed Class Pointer Space不是必须有的,如果设置了-XX:-UseCompressedClassPointers,或者-Xmx设置大于32G,就不会有这块内存,这种情况下klass都会存在NoKlass Metaspace里。
  • NoKlass Metaspace
  1. NoKlass Metaspace专门来存klass相关的其他的内容,比如method,constantPool等,可以由多块不连续的内存组成。
  2. 这块内存是必须的,虽然叫做NoKlass Metaspace,但是也其实可以存klass的内容,上面已经提到了对应场景。
  3. NoKlass Metaspace在本地内存中分配。

这里我们说的类型指针指向的是Klass Metaspace地址。

指针压缩

  1. 64位平台上默认打开
  2. 设置-XX:+UseCompressedOops压缩对象指针, oops指的是普通对象指针(ordinary object pointers), 会被压缩成32位。
  3. 设置-XX:+UseCompressedClassPointers压缩类指针,会被压缩成32位,这里指类对象。
    如果设置了-XX:-UseCompressedClassPointers,或者-Xmx设置大于32G,则这个参数不生效。

参考这篇文章:https://blog.csdn.net/liuxiao723846/article/details/91981757

为什么要对齐

image.png

相关文章

  • java 内存布局

    Java 内存的布局主要是统计Java对象占用内存的大小。 Java对象的内存布局:对象头(Header)、实例数...

  • Java对象

    Java对象的内存布局?对象的访问?new对象的过程? 一、Java对象的内存布局 对象的创建过程就是在堆上分配实...

  • Java对象

    本文以HotSpot虚拟机为例,介绍Java对象在虚拟机中存储和使用方式。 对象的内存布局 对象在内存中存储布局可...

  • 对Java对象的深入认识(三)

    1. Java对象 1.1 Java对象的组成 ​ 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3...

  • java.jvm.自动内存管理机制.hotspot虚拟机对象.对

    java对象在内存中的结构(转帖):里面说明了在32位下Integer对象和integer数组内存布局。 对象的内...

  • Synchronized原理

    1、认识JAVA对象的组成结构 对象的内存结构:在JVM中,对象在内存中的布局分为三块区域:对象头、实例数据和对齐...

  • Java中对象的内存布局

    所谓内存布局,指的是一个对象在内存中的组成。通常由三部分组成 对象头(包含MarkWord、Klass Point...

  • JVM对Synchronized关键字的优化

    Java对象头和Monitor是实现synchronized关键字的基础。 对象头 对象头在内存中的布局: 对象头...

  • java对象的内存布局

    1.java的内存布局 对象在内存中的存储可以分为三个区域:对象头(Header),实例数据(Instance D...

  • JAVA

    JAVA java中接口与抽象类的区别? 简述jvm的内存布局? java对象创建的过程? java重载与重写的区...

网友评论

      本文标题:Java中对象的内存布局

      本文链接:https://www.haomeiwen.com/subject/kgfrpltx.html