网站首页 > java教程 正文
对象的创建过程
new对象
image-20230226144541919
1:首先判断这个类有没有加载过,没有加载过的先加载到我们JVM内存中。
2:分配内存
- 指针碰撞:默认使用,如果JVM堆中内存绝对规整,使用过的内存放一边,空闲的内存放另一边。中间放着指针分界点,在分配内存的时候将那个指针向空闲空间移动一段对象大小的距离。(垃圾收集器用的是标记整理)
- 空闲列表:JVM堆中内存不规整,已使用和未使用的相互交错,没办法用指针碰撞,JVM必须维护一个列表,记录哪些内存块可用,在分配的时候从列表中找到一块足够放下对象的空间给对象实例,并更新列表的记录。(垃圾收集器用的是标记清理)
- 在分配内存的时候,肯定会有并发的问题,不管哪种都存在这种问题,要争抢内存。
- 解决并发问题的方法:1:CAS失败重试。2:本地线程分配缓冲,为了避免争抢,本地线程在堆中划一块自己专属的内存空间,本地线程只往自己的 内存空间中创建对象,默认是开启的,-XX:TLABSize 指定TLAB大小,不设置的话默认是Eden的百分之一。如果放不下就走cas。
3:初始化:给变量赋上默认值。类加载的时候会给静态变量赋上默认值。
4:设置对象头:
image-20230226145734134
对象头里边主要包含Mark Word结构(中间那个图32位的)
正常的对象,没有加锁的对象就是无锁态那一行,前25保存hashCode,后4为保存分代年龄<=15,后边3位保存锁的状态。
Klass Pointer类型指针,一个对象new出来是在堆中,在这个对象头部区域有根指针指向元空间的类元信息,就是这个类型指针。比如 getClass,getMethod,getFileds… ….是通过这根指针找到的。
如果数组的话,会多出一块,存放数组长度占4个字节,只有数组才会有。
通过ClassLayout.parseInstance查看对象头
public static void main(String[] args) {
System.out.println("Object --- ");
ClassLayout layout = ClassLayout.parseInstance(new Object());
System.out.println(layout.toPrintable());
System.out.println("数组 --- ");
ClassLayout layout1 = ClassLayout.parseInstance(new int[]{});
System.out.println(layout1.toPrintable());
System.out.println("B对象 --- ");
ClassLayout layout2 = ClassLayout.parseInstance(new B());
System.out.println(layout2.toPrintable());
}
static class B {
int id;
String name;
byte aByte;
Object o;
}
输出结果为:
Object ---
java.lang.Object object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
12 4 (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
数组 ---
[I object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 6d 01 00 f8 (01101101 00000001 00000000 11111000) (-134217363)
12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
16 0 int [I.<elements> N/A
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
B对象 ---
com.example.JvmModel.JvmTest$B object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 65 cc 00 f8 (01100101 11001100 00000000 11111000) (-134165403)
12 4 int B.id 0
16 1 byte B.aByte 0
17 3 (alignment/padding gap)
20 4 java.lang.String B.name null
24 4 java.lang.Object B.o null
28 4 (loss due to the next object alignment)
Instance size: 32 bytes
Space losses: 3 bytes internal + 4 bytes external = 7 bytes total
Process finished with exit code 0
Instance size:为我们对象的大小。OFFSET:偏移量。SIZE:大小
我这电脑是64位,
Object内存:
前两行是Mark down 。
第三行是Klass Point,这是开启对象指针压缩,默认开启。没有开启的话,会由8个字节组成。。
最后一行是对齐。八个字节对齐,8的整数倍。是我们对象寻址效率最优的方式。
一个Object其实大小为12字节,但是为了要对齐8的整数倍,扩充4个字节,一个Object的大小为16个字节。
数组内存:
前两行依然是Mark down。
第三行是Klass Point。
第四行是数组的长度。
他的内存大小是16个字节,它不需要对齐。
B对象:
前三行… … markdown Klass Point
B.id:int占4个字节。
B.aByte:byte,占用一个字节。它的下一行是内存对齐,对齐成为4个字节。
B.name:String占用4个字节,存放的内存地址。这是开启对象指针压缩,默认开启。没有开启的话,会由8个字节组成。
B.o:对象占用4个字节,存放的内存地址。
最后一行对齐8。
5:执行init方法。将成员变量真正的赋值,然后还会调用对象的 构造方法。
猜你喜欢
- 2025-07-09 5分钟读懂C#中TcpClient、TcpListener和Socket三个类的角色
- 2025-07-09 对象组成与Java内存模型JMM分析(java对象在内存中存储的结构)
- 2025-07-09 JVM对象内存分配详细过程(栈上分配->TLAB->老年代->Eden区)
- 2025-07-09 三石说:java基础 类与对象(java第十一章类和对象)
- 2025-07-09 java对象创建过程和JVM对象内存分配过程(转载)
- 2025-07-09 每天一篇Java面试之框架热门面试答案汇总
- 2025-07-09 普通java对象的实例化过程(java实例化对象new)
- 2025-07-09 详解JVM中的Java对象(jvm的xmn)
- 2025-07-09 JOL:Java 对象内存布局(java对象内存空间分配安排)
你 发表评论:
欢迎- 最近发表
-
- 你真的会用 Java 中的线程池吗?多个企业级线程池工具类封装实践
- 线程池的实现原理、优点与风险、以及四种线程池实现
- Java线程池ThreadPoolExecutor实现原理剖析
- 深入分析线程池的实现原理(线程池是干嘛的)
- 一文搞懂JAVA线程池工作原理(java线程池的工作流程)
- Java线程池的工作原理(java线程池的实现原理)
- 5分钟读懂C#中TcpClient、TcpListener和Socket三个类的角色
- JVM对象的创建过程(jvm运行过程中创建的对象一般存放在方法区)
- 对象组成与Java内存模型JMM分析(java对象在内存中存储的结构)
- JVM对象内存分配详细过程(栈上分配->TLAB->老年代->Eden区)
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)