对象的内存布局
一、对象的创建过程
1、创建对象主要分一下几个步骤:
- class loading
- class linking(verification preparation resolution)
- class innitializing
- 申请对象内存
- 成员变量赋默认值
- 调用构造方法(1.成员变量赋初始值 2.执行构造方法语句)
2、解释一下上面的步骤:
第一步是将class文件load到内存中,第二步是linking,主要包括三小步:1.verification校验 2.preparation准备 给类的静态常量赋默认值 3.resolution做一个解析,第三步类初始化,将静态变量赋初始值的同时执行静态语句块。创建完对象之后需要向申请内存,成员变量赋默认值,然后调用构造方法在字节码层面,调用构造方法时将成员变量赋初始值,接下来调用构造方法语句super()调用父类。
二、对象的布局
作为对象的内存布局来讲主要分为两种:第一种叫普通对象 , 第二种叫做数组对象。
普通对象首先有:
-
-
- 第一有对象头,在hotsport中叫做markword长度为8个字节
- 第二个是ClassPointer 指针
- 第三个是实例数据
- 第四个是padding对齐,这个对齐是8的倍数
-
普通对象,首先有一个对象头markword 8个字节
三、对象头内具体都包括什么
对象头中的信息非常复杂,而且每一个版本的实现还不一样,而且markdown这个东西在不同的对象记录的东西也是不一样的,就以JDK8 Hotsport实现来说:
markdown里面装的什么?
第一是锁的信息 后三位分别是偏向锁的标志位、锁的标志位,代表对象有没有被锁定;第二是GC回收的次数以及分代年龄;第三是hashcode值;第四是线程id。
四、对象定位
对象的定位有两种:1、语柄池 2、直接指针
例如:T t = new T(); 这里的t是如何找到他的对象,第一种方式是语柄池,通过间接指针,第一步把 t 指向两个指针 一个指向对象一个指向t.class。第二种是直接指,直接指向对象然后指向t.class 两种方式没有优劣之分,有的虚拟机用第一种有的用第二种;第一种需要先找到一个指针然后找下一个,第二种的效率比较高直接找到对象,两者在gc方面的效率方面第一种比较高,这里hotsport使用的是第二种。
五、对象如何分配
首先new一个对象的时候,先往栈上分配,栈上如果可以分配下就分配在栈上,然后栈上一弹出就没了,如果栈上分配不下,对象特别的大直接分配到堆内存,也就是老年代,如果对象不大,首先会进行线程本地分配,如果分配不下,会找到伊甸区然后进行GC过程,在GC的过程中年龄到了一定大小就会直接进入老年代,如果年龄没到,就会一次一次GC直到年龄到达为止;
以上就是对象的内存布局,如果有不足和有问题的地方,希望大家提出来,一起讨论一起进步!!!!!!