@chenxuxiong
2016-05-31T15:22:54.000000Z
字数 1058
阅读 492
对象的创建,内存布局,访问定位,内存分配
JAVA虚拟机
1.对象的创建:
- 虚拟机遇到new指令时,先检查参数是否在常量中定位到一个类的符号引用,在检查是否已加载、解析和初始化过,如果没有,则先执行类加载过程
- 在类加载检查后,虚拟机为通过指针碰撞法或空闲列表法,来对象分配内存堆空间,
- 在分配完成后,将分配到的内存初始化为零值(不包括对象头)
- 设置对象布局,如:这个对象是哪个类的实例、如何才能找到这个类的元数据信息、对象的哈希码、对象的GC分代年龄等等。
- 最后,执行初始化方法
2.对象的内存布局
- 内存布局区域分为:对象头,实例数据,对齐填充。
- 对象头包含两部分
- 第一部分用于存储对象自身的运行时数据,如哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等
- 另一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定对象是哪个类的实例。
- 实例数据则是对象真正存储的有效信息,也就是代码中定义的各种类型的字段的内容。
- 对齐填充则不是必然存在的,它仅仅起着占位符的作用。当对象实例数据部分没有对齐时,就需要对齐填充补全。
3.对象的访问定位
- 句柄:堆中画出内存作为句柄池,Java栈局部变量表中的refernce存放的就是对象的句柄地址,句柄包含对象实例数据(堆)与对象类型数据(方法区:常量,静态变量)的具体地址信息
对象被移动只需改变句柄池的指针,reference本身不用系应该
- 指针:java堆对象的布局考虑如何放置访问类型数据的相关信息,refernce存储的是对象地址
HotSpot 速度快
4.对象内存分配
1.分配方法
- 指针碰撞法和空闲列表法
- 指针碰撞:假设堆内存绝对规整,所用过的内存放一边,空闲的内存放一边,中间用一个指针作为分界点的指示器,把这个指针向空闲区域挪动一段与对象大小相等的距离即可分配内存。
- 如果选用这种方法,需要收集器具有压缩整理的功能。如:serial,ParNew
- 空闲列表:如果内存不规整,已使用内存与空闲内存相交错,就没办法进行指针碰撞。所以虚拟机必须维护一个列表,来记录哪些内存块可用的,在分配的时候从列表中找到一块足够大的内存划分给对象实例,同时更新列表记录。
2.分配区域
- 1、对象优先在Eden区内分配。
- 2、当每熬过一次minorGC,年龄+1,到达一定程度就进入老年代。
- 3、大对象也会直接进入老年代(可以指定大小)。
- 4、还有一种情况,当survivor空间中相同年龄所有对象大小的总和大于suvivor空间的一半,年龄大于或等于该年龄的对象也可以直接进入老年代。