对象java_虚拟机

HotSpot虚拟机对象探秘(Java对象具体是如何创建的)

2017-04-18  本文已影响15人  今有所思

下文主要探讨HotSpot虚拟机在Java堆中对象分配、布局和访问的全过程。

对象的创建

在 Java 语言层面上,我们创建一个对象是如此简单:ClassA intance = new ClassA(); 但是在虚拟机内部,其实经历了非常复杂的过程才完成了这一个程序语句。

1、虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化过。如果没有,就得执行类的加载过程;

2.、在类加载检查通过后,虚拟机将为新生对象分配内存。对象所需内存大小再类加载完成后便可确定。目前有两种做法,使用哪种方式是由垃圾收集器是否带有压缩整理功能决定的:

TLAB

那么在分配内存的时候,可能会出现多线程问题,解决方式有 CAS 乐观锁,以及 TLAB方式。TLAB的全称是 Thread Local Allocation Buffer。

每个线程 JVM在内存新生代Eden Space中开辟了一小块线程私有的区域,称作TLAB(Thread-local allocation buffer)。默认设定为占用Eden Space的1%。在Java程序中很多对象都是小对象且用过即丢,它们不存在线程共享也适合被快速GC,所以对于小对象通常JVM会优先分配在TLAB上,并且TLAB上的分配由于是线程私有所以没有锁开销。因此在实践中分配多个小对象的效率通常比分配一个大对象的效率要高。

也就是说,Java中每个线程都会有自己的缓冲区称作TLAB(Thread-local allocation buffer),每个TLAB都只有一个线程可以操作,TLAB结合bump-the-pointer技术可以实现快速的对象分配,而不需要任何的锁进行同步,也就是说,在对象分配的时候不用锁住整个堆,而只需要在自己的缓冲区分配即可。

3、内存清零:给内存分配了空间之后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头)。如果使用TLAB,这一工作过程也可以提前至TLAB分配时进行。

4、 接下来要对对象进行必要的设置,比如

这些信息都放在对象头中。

5、 上面的步骤都完成后,从虚拟机角度来看,一个新的对象已经产生了,但是从 Java 程序的视角来看,对象创建才刚刚开始——<init> 方法还没有执行,所有的字段都还为零。把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来。

对象的内存布局

首先我们要知道的是:在 HotSpot 虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instantce Data)、对齐补充(Padding)。当然,我们不必要知道太深入,大概知道每个部分的作用即可:

对象的访问定位

Java程序需要通过栈上的reference数据来操作堆上的具体对象。访问方式有使用句柄和直接指针两种。

  1. 句柄访问 Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息!

    句柄访问
  2. 直接指针访问 Java堆对象的布局中必须考虑如何放置访问类型数据的相关信息,reference中存储的就是对象地址!

    直接地址访问
两种访问方式的比较

HotSpot虚拟机采用指针访问方式进行对象访问,从整个软件开发范围看,各种语言和框架使用句柄来访问的情况也非常常见。

上一篇 下一篇

猜你喜欢

热点阅读