天天看点

深入理解java虚拟机的相关知识(2)--对象的创建,内存布局,内存分配与回收,访问定位一 java堆中对象的创建过程二 对象的内存布局三 内存分配与回收策略四 对象的访问定位

一 java堆中对象的创建过程

讨论限于普通java对象,不包括数组和对象等。

  1. 虚拟机遇到new指令,首先检查这个指令的参数是否能在常量池中定位到一个类的符号引用,检查此类是否被加载过,如果没有先执行类的加载过程(加载。验证,准备,解析,初始化)
  2. 在类加载完成后,为新生对象分配内存。分配方式有“指针碰撞”(指针作为空闲空间和对象空间的分界点)和“空闲列表”(更新列表记录)。
  3. 内存分配完成后,虚拟机将分配的内存空间初始化为零值(不包括对象头)。
  4. 虚拟机对对象进行必要的设置。设置对象头中信息(类的元数据信息,对象的hash码,对象的GC分代年龄等)
  5. 执行init方法

二 对象的内存布局

3块区域:对象头 实例数据 对齐填充

对象头:包括两部分信息。

  1. 用于存储对象自身的运行时数据,如hash码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等
  2. 类型指针,即对象指向它的类元数据的指针,通过此指针确定这个对象是哪个类的实例。

实例数据:对象真正存储的有效信息,也就是程序代码中所定义的各种类型的字段内容。

对齐填充:占位符的作用,虚拟机要求对象起始地址必须是8字节的整数倍,也就是对象的大小,对象头大小,实例数据均为8字节的整数倍。

三 内存分配与回收策略

大多数情况下,对象在新生代Eden区中分配,大对象直接进入老年代,长期存活的对象将进入老年代,如果Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可直接进入老年代。

当Eden区没有足够的空间进行分配时,虚拟机将发起Minor GC

Minor GC:发生在新生代的垃圾收集动作,因为java对象大多都具备朝生夕灭的特性,所以Minor GC会比较频繁,一般回收速度比较快。

Major GC/Full GC:发生在老年代的GC,出现了Major GC ,经常会伴随至少一次的Minor GC。一般会比Minor GC慢10倍以上。

四 对象的访问定位

java程序需要通过栈上的reference数据来操作堆上的具体对象,而reference类型只规定了一个指向对象的引用,并没有定义如何定位和访问对象的具体位置。目前主流的访问方式有使用句柄和直接指针两种。

如果使用句柄访问,java堆中将会划分一块内存来作为句柄池,referenece中的存储就是对象的句柄地址,句柄中包含对象实例数据和类型数据各自的具体地址信息

优势:稳定的句柄地址,在对象被移动时只会改变句柄实例数据指针,而reference本身不需要修改

深入理解java虚拟机的相关知识(2)--对象的创建,内存布局,内存分配与回收,访问定位一 java堆中对象的创建过程二 对象的内存布局三 内存分配与回收策略四 对象的访问定位

如果使用直接指针访问,那么reference中存储的直接就是对象地址。java堆中存放的是对象实例数据和对象类型数据的指针。

优势:速度更快,节省了一次指针定位的时间开销,java虚拟机一般使用第二种方式进行对象访问,但从整个软件开发的范围来看,各种语言和框架使用句柄的情况也很十分常见。

深入理解java虚拟机的相关知识(2)--对象的创建,内存布局,内存分配与回收,访问定位一 java堆中对象的创建过程二 对象的内存布局三 内存分配与回收策略四 对象的访问定位

下一篇:深入理解java虚拟机的相关知识(3)--垃圾收集机制