发布日期:2025-03-07 00:45 点击次数:53
一、内存分配
这部分我们说一下对象在 java 堆中是如何分配、布局、访问以及内存分配的原则。
1、对象的创建
我们用 new 来创建对象,来看看系统运行到 new 时,虚拟机在干什么。此时的类就像一块肉,他要经过层层安检,才能到达人类的饭桌。
(1)查看在常量池中是否有对应的符号引用。【在方法区中进行】
(2)查看此类是否被加载、解析和初始化过。【在方法区中进行】
(3)领取新生对象的内存。有两种方式:指针碰撞和空闲列表。【在堆中进行】
(4)将分配到的内存空间初始化为零。
(5)对对象进行必要的设置,比如其实哪个类的实例,对象的哈希码之类的。这些信息存放在对象的对象头中。
(6)如果 java 代码对对象进行了赋值,则会走到第六步,执行 <init> 方法。此方法的作用就是对对象进行初始化。
2、对象的内存布局
对象在内存中的存储布局分为三个部分:对象头 + 实例数据 + 对其补充
对象头
对象头里面有两部分信息:
(1)运行时数据,包括哈希码、GC 分代年龄、锁状态标志等。
(2)类型指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
实例数据
实例数据中存放的是代码中定义的各种类型的字段内容。
对其填充
对齐填充起的是占位符的作用,不是必然存在的,其只要保证对象的大小是 8 字节的整数倍即可。
3、对象的访问定位
建立完对象后,我们就可以使用对象了。通过句柄和直接指针两种方式。
句柄
句柄访问就是在 java 堆中划分出一块内存区域作为句柄池,句柄中包含了实例数据和类型数据各自具体的地址信息。
直接指针
直接指针之所以 “直接”,是因为它去除了句柄这个中介。所以在速度上比句柄快。在 HotSpot 虚拟机中,使用的是这种方式。
说完了对象在 java 堆中是如何分配,布局和访问的,接下来我们说说内存分配的原则。
4、内存分配的原则
堆大致分为新生代,老年代,永久代。对象的内存分配主要分配在新生代的 Eden 区,少数情况下会直接分配到老年代中。分配的规则不是 100% 固定的,取决于垃圾收集器组合和参数设置等。下面有几条分配原则可供参考。
对象优先在 Eden 分配大对象直接进入老年代长期存活的对象将进入老年代动态对象年龄判定空间分配担保
上一篇:没有了