[JVM]深入对象的创建和内存分配

网友投稿 752 2022-11-01

[JVM]深入对象的创建和内存分配

[JVM]深入对象的创建和内存分配

1、对象的创建

java是面向对象的语言,因此对象的创建无时无刻都存在。在语言层面,使用new关键字即可创建出一个对象。但是在虚拟机中,对象创建的创建过程则是比较复杂的。

首先,虚拟机运到new指令时,会去常量池检查是否存在new指令中包含的参数,比如new People(),则虚拟机首先会去常量池中检查是否有People这个类的符号引用,并且检查这个类是否已经被加载了,如果没有则会执行类加载过程。

给对象分配内存:在类加载检查过后,接下来为对象分配内存当然是在java堆中分配,并且对象所需要分配的多大内存在类加载过程中就已经确定了。为对象分配内存的方式根据java堆是否规整分为两个方法:1、指针碰撞(Bump the Pointer),2、空闲列表(Free List)。指针碰撞:如果java堆是规整的,即所有用过的内存放在一边,没有用过的内存放在另外一边,并且有一个指针指向分界点,在需要为新生对象分配内存的时候,只需要移动指针画出一块内存分配和新生对象即可;空闲列表:当java堆不是规整的,意思就是使用的内存和空闲内存交错在一起,这时候需要一张列表来记录哪些内存可使用,在需要为新生对象分配内存的时候,在这个列表中寻找一块大小合适的内存分配给它即可。而java堆是否规整和垃圾收集器是否带有压缩整理功能有关。

线程安全问题

初始化对象: 内存分配后,虚拟机需要将每个对象分配到的内存初始化为0值(不包括对象头),这也就是为什么实例字段可以不用初始化,直接为0的原因。

执行构造方法:接来下,虚拟机对对象进行必要的设置,例如这个对象属于哪个类的实例,如何找到类的元数据信息。对象的哈希吗、对象的GC年代等信息,这些信息都存放在对象头之中。

执行完上面工作之后,所有的字段都为0,接着执行指令,把对象按照程序员的指令进行初始化,这样一个对象就完整的创建出来。

2、对象的内存布局

对象在内存的存储布局中包括:对象头、实例数据、对齐填充

对象头(Header):包含两部分信息。1、存储对象自身的运行时数据,比如哈希码、GC分代年龄等;2、类型指针:通过这个指针确定这个对象属于哪个类。

实例数据(Instance Data):存储代码中定义的各种类型的字段内容。

对齐填充(Padding):这部分信息没有任何意义,仅仅是为了使得对象占的内存大小为8字节的整数倍。

3、对象的访问定位

创建对象是为了使用对象,java程序需要通过栈上的reference数据来操作栈上的具体对象。目前主流的访问对象方式有使用句柄和直接指针两种。1、使用句柄方式:会在java堆中创建一个句柄池,reference指向的这块句柄池,句柄池中包括两个指针,其中一个指针指向对象实例数据,另外一个指针指向对象的类型数据。2、使用指针的方式:reference存储的直接就是对象的地址。

两种方式各有各的特点,如果使用句柄方式的话,最大的好处是reference存放的是稳定的句柄地址,在对象移动时只会改变句柄中的实例数据指针,而reference本身不需要修改。使用指针的方式优势则是速度快,并且省去了一次指针定位的开销。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:更优雅的音乐下载体验,为程序员而设计,使用Go语言编写
下一篇:171. Excel Sheet Column Number
相关文章

 发表评论

暂时没有评论,来抢沙发吧~