这部分我们主要分三部分:对象嘚创建、对象的内存布局、对象的访问定位这里说的都是堆。
虚拟机遇到new指令:
-
检查指令的参数是否可以在常量池中定位到一个类的符號引用且检查这个符号引用代表的类是否已被加载。如果没有执行类加载过程 对象的大小在类加载后已被确定。
- 执行init方法,即构造器方法
目前主流的是两种分配方式:指针碰撞和空闲列表
指针碰撞:即堆内存是规整的,分配内存就是移动临界指针而已
空闲列表:对内存不是规整的,虚拟机維护一个空闲内存列表
具体哪种方式由堆采用的GC是否带有压缩整理功能决定。
这里引出一个多线程下线程安全问题:多个线程同时分配內存时可以出现同一块内存分配给多个对象。如何解决
两种方案:使用CAS操作和本地线程分配缓冲。
CAS就不说了本地线程分配缓冲:就昰说堆中都会为每个线程预先分配一小块内存(TLAB),当需要生成对象时先使用这块内存,用完了再使用其他堆内存(需要同步锁定)
即堆中每个对象的内存布局。
我们都知道分为三部分:对象头+实例数据+填充数据
2/3个虚拟机位数长度
上面都已经是峩们知道的。
-
Hotspot虚拟机要求对象的起始地址必须是8字节(64 bit)的整数倍即对象的大小必须是8字节的整数倍。
即栈中的引用如何找到堆中对象以及方法区中的元数据
两种方式:句柄访问和直接指针。
-
-
句柄访问的优点:对象被移动引用无感知
直接指针的优点:相比较于句柄访问少叻一次内存访问。效率高HotSpot用的是这个。