Java创建对象分配内存

Java创建对象分配内存

一:对象内存的规划:

        Java虚拟机在遇到一条 new 指令的时候,会首先检查,这个类是否已经被加载、解析、初始化过,如果没有,就要执行类加载的过程。在检查通过后,接下来,Java虚拟机会为这个对象在堆内存里面分配内存空间。对象内存的空间规划有两种方案:

        第一种:如果对内存空间是规整的,也就是说,堆内存空间使用过的在一边,没有使用过的在一边(就相当于往一个容器里面加水,容器从下往上分为用过的和没有用过的)。当需要分配新的内存的时候,只需要将指针指向一个原来指针所指向的位置+要创建对象所需要的内存。

        第二种:如果对内存是先对散的,不是连续的,Java虚拟机需要维护一个空闲内存列表。这个类表里面记录着那些位置内存是没有使用的,当需要创建对象时,从空闲列表中找到一个合适的内存块,并分配给对象。

这两种方案具体使用哪一个与Java垃圾回收算法相关,如果垃圾回收算法以“复制算法”为基础,如:Serial、ParNew 垃圾回收算法,虚拟机会使用第一种方案,如果是以“标记清除”算法为基础 如CMS 则使用第二种方案。

除了空间规划外,还需要考虑并发问题,因为在Java虚拟机中,对象创建时很频繁的操作,如果对个线程在创建对象的时候,有可能,得到原来空间指针是同一个,以得到的空间指针为基础规划对象内存,会出现内存覆盖的问题,如:使用第一种方案分配时,一共有6个茅坑,1、2、3是在使用中,现在指针指向3,如果同时有多个人想上厕所,需要获取,当前指针的位置,在没有加锁的情况下,新来的这些人,获取的都是第四个茅坑,结果。。。。。。,所以针对这样的问题,虚拟机有两种方案:1,使用CAS失败重试的方式,保证分配内存的原子性,2:是在线程创建对象的时候,为每个线程,分配一小块单独的内存(TLAB),这样在线程创建对象的时候,只操作当前线程的的内存(TLAB),只有线程的内存使用完毕后,才需要加锁为线程增加一块内存,虚拟机是否使用TLAB 可以通过-XX:+/-UseTLAB 参数设置。

二:对象属性的初始化:

        在分配完内存后,虚拟机需要将分配的空间进行初始化,经要创建对象的属性设置成初始值,这样可以保证,属相在没有设置值得时候可以被访问。接下来,设置对象的对象头,就与对象相关的描述信息。如:这个对象属于哪一个类,对象的哈希码,对象GC的年龄等。

三:调用类的构造方法:

        在走完一 二步骤后,对于虚拟机来说,对象已经创建完成,对用程序来说,对象还么有初始化完成,应该为还没有嗲用构造方法,通过调用构造方法,来为对象的属性重新设置,程序员设置的值。走完以后,一个对象,才算初始化完成

你可能感兴趣的:(Java)