1 类加载检查
当JAVA虚拟机碰到一条new的字节码,首先会去检查指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否被加载、解析和初始化过.如果没有,则进行相对应都类加载过程。
2 对象布局
在类加载完成后,就进行内存布局,内存的大小在类加载的时候就可以确认大小了,为对象分配空间,其实就是在堆空间划分一块大小出来,存放刚创建的对象。
对象的内存分配有两种:指针碰撞,空闲列表
(1) 指针碰撞
假设java堆内存空间是绝对规整的,所有被使用过的对象都是放在一起,空闲的内存放在另外一边,中间放着一个指针为分界点的指示器,那么内存分配就仅仅把那个指针向空闲方向挪动挪动一段与堆内存大小相等的距离,这种就称为指针碰撞。
(2)空闲列表
虚拟机维护了一块列表,哪些内存是可用的,在分配的时候从列表中找一块足够大的空间给对象,并更新在列表记录上.这种方式被称为空闲列表(Free List)。
选择哪种分配方式由java堆是否规整决定.
分配内存的时候,是一种频繁的操作,存在并发的问题,虚拟机提供有两种解决方案CAS分配内存
(1)CAS分配内存
虚拟机采用CAS配上失败后在重试分配内存
(2)本地线程分配(TLAB)
那个线程要分配内存,就在那个线程本地缓存区,只有等本地缓冲区用完了,分配新的缓存区时才需要同步锁定.
3 对象初始化
虚拟机把分配到内存空间的(不包含对象头)进行初始化为零值
4 初始化java对象头
初始化对象头信息,比如对象的哈希吗(实际上在调用的时候才进行计算),对象是哪个类的实列,如何才能找到类的元数据信息,对象GC的分代年龄。
5 对象init化
实际上就是调研对象new的方法,也就是c++中init进行程序设置的操作.列如: new A(1,2);实际上就是调用A的构造方法
看了深入理解JAVA虚拟机,我有两点不明白
第一点: 常量池中定位到一个类的符号引用,常理池存储了哪些信息,是那种数据结构,为什么要去常理池中去获取
第二点: 选择哪种分配方式由java堆是否规整决定? 虚拟机如何知道java堆是否规整,怎么做的?
后续在解答 2021-01-06