创建对象很简单:new一个啊,但在Java的虚拟机中,引用“深入理解Java的虚拟机”中的这样一句话:

虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用表的类是否已被加载,解析和初始化过。如果没有,那必须先执行相应的类加载过程。在类加载检查通过后,接下来虚拟机将为新生对象分配内存。

长长一句话很难记住它,我对此进行一下缩句:

    1.先是否能定位到,再检查是否被加载,解析并初始化过

    2.若没有则执行类加载,为这个新对象分配内存

然而依我理解:

分配一块内存对象的时候,就像:

第一种情况:把这个过程想象成是规整的:(专业术语:指针碰撞)

爱玛电瓶车的时速表一样,加油门指针向右走,左右分两块;

第二种情况:不规整:(专业术语:空闲列表)

里面很乱,要维护并寻找块大空间给这个对象。

这两种情况需要垃圾收集器是否带有压缩整理功能决定。

怎么决定呢:一系列算法,本文不做描述。

在这个过程需要注意:如果频繁的创建对象,这个指针岂不是会晕哭?了,

在并发情况下:可能正在给阿分配内存,还没好,又来了个B,指针就晕菜了。

解决以上的问题有两种方案:

一:对分配内存空间的动作进行同步处理

二:把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在的的的Java堆中预先分配一小块内存,称为本地线程分配缓冲。

哪个线程要分配内存,就在哪个线程的TLAB上分配,只有TLAB用完并分配新的TLAB时,才需要同步锁定。

是否使用TLAB,可以通过-XX:+/-使用TLAB参数来设定。

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

这一步操作保证了对象的实例字段在的的Java的代码中可以不赋初始值就直接使用,能程序访问到这些字段的数据类型所对应
的零值。

接下来,虚拟机要对对象进行必要的设置。

从虚拟机的视角来看,一个新的对象已经产生了。

从java程序的视角来看,对象创建才刚刚开始—— <init>方法还没有执行,所有的都字段还为零所以,一般来说(由字节码中是否跟随invokespecial指令所决定) ,新执行之后指令会接着执行<init>方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来。

上面大段话可以用如下图进行理解:(图片来源于网络)

然而:创建对象就这么简单完事了并不是!

引出如下问题:

1.类加载器是怎么执行的?

2.对象所需内存的大小在类加载完成后是如何确定下来的?

3.对象头的设置及具体内容阐述?等等问题

后续章节将做详细探讨?------------------------------------------- -------------------------------------------------- ---------

文章部分内容来源于深入理解Java虚拟机第二版中

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐