7.jvm对象内存布局
目录
- 概述
- 对象里的三个区
- 对象头
- 验证
- 代码
- 控制台输出
- 分析
- 验证2
- 代码
- 控制台输出
- 实例数据
- 对其填充
- 访问对象
- 结束
概述
jvm对象内存布局详解。
相关文章在此总结如下:
| 文章 | 地址 |
|---|---|
| jvm基本知识 | 地址 |
| jvm类加载系统 | 地址 |
| 双亲委派模型与打破双亲委派 | 地址 |
| 运行时数据区 | 地址 |
| 运行时数据区-字符串常量池、程序计数器、直接内存 | 地址 |
| jvm中对象创建流程与内存分配 | 地址 |
对象里的三个区
对象里有啥?

对象头
对象头:8字节,如果是数组12字节(记录数组长度,占4字节)
-
标记字段:存储对象
运行时自身数据- 默认:对象Hashcode、GC分代年龄、锁状态
- 存储数据结构并不是固定的
-
类型指针:对象指向类元数据的指针
- 开启指针压缩占4字节、不开启8字节 (jdk1.6之后默认是开启的)
-
数组长度:如果是数组,则记录数组长度,占4个字节
-
对其填充:保证数组(针对的是数组)的大小永远是8字节的整数倍
32位Markword是可变的数据结构,对象头总大小固定8字节

Markword 占4个字节,共32位。
64位Markword是可变的数据结构,对象头总大小固定12字节


验证
打印空对象的内存而已信息
代码
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
执行代码
package com.fun.info;
import org.openjdk.jol.info.ClassLayout;
public class ObjLock {
public static void main(String[] args) {
Object o = new Object();
System.out.println("new Object:"+ ClassLayout.parseInstance(o).toPrintable());
}
}
控制台输出

分析
- 首先对象头是包含
Markword和类型指针这两部分信息 - 开启指针压缩的情况下,存放 Class 指针的空间大小是4字节,Markword是8字节,对象头为12个字节
- 新建 Object 对象,会在内存占用16个字节,其中
Header占12个(Markword 占8个 + ClassPoint 占 4个),没有实例数据,补充对齐 4 个字节
验证2
基本数据类型和包装类的内存占用情况
| 数据类型 | 内存占用 (byte) |
|---|---|
| boolean | 1 |
| byte | 1 |
| short | 1 |
| char | 2 |
| int | 4 |
| float | 4 |
| long | 8 |
| double | 8 |
| Boolean | 4 |
| Byte | 4 |
| Short | 4 |
| Character | 4 |
| Integer | 4 |
| Float | 4 |
| Long | 4 |
| Double | 4 |
代码
package com.fun.info;
import org.openjdk.jol.info.ClassLayout;
public class ObjLock2 {
public static void main(String[] args) {
Student o = new Student();
System.out.println("new Object:"+ ClassLayout.parseInstance(o).toPrintable());
o.setAge(10);
o.setFlag(true);
o.setName("abc");
System.out.println("赋值 new Object:"+ ClassLayout.parseInstance(o).toPrintable());
}
static class Student{
private boolean flag;
private int age;
private String name;
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
}
}
控制台输出


总结: 对象从创建,对象的大小就已确定了。
实例数据
对象内部的成员变量
对其填充
8字节对象,保证对象大小是8字节的整数倍。
访问对象
如何访问对象?


两种方式如上两图:
- 1.句柄
- 2.直接指针
结束
至此,jvm对象内存布局就说得明明白白了,如有疑问,欢迎评论区留言。
