·加载检查:当在代码中使用到某个类时,jvm需要先检查该类是否已经加载到内存中。如果没有,jvm会通过类加载器去加载这个类,这个过程称为类加载检查。类加载检查的主要任务是确保所需的类在内存中可用,这是程序正常运行的前提。
·内加在检查还包括对类的合法性进行检查,比如检查类的魔术版本号等信息,以确保类文件的完整性和正确性。此外内加在检查还会检查类是否已经被加载过,以避免重复加载,提高运行效率。
·分配内存:一旦类加载检查通过,jvm需要在堆内存中为对象分配内存空间。这个过程需要考虑到对象的大小以及堆内存的可用空间。在进行内存分配时,jvm会根据对象的大小来决定在堆内存中分配多少空间。

如果对象比较小,jvm会选择使用快速分配策略,例如指针碰撞或者空闲列表。指针碰撞是一种简单的内存分配方式,它将堆内存一分为二,一边用于已分配对象,另一边用于未分配对象。通过移动指针来实现内存分配,而空闲列表则是将堆内存划分为一系列大小不等的内存块。
通过维护一个空闲列表来记录可用的内存块。当需要分配内存时,从空闲列表中选择合适大小的内存块进行分配。除了考虑对象大小外,jvm还需要考虑堆内存的可用空间。如果堆内存的可用空间不足以容纳对象,就会触发垃圾回收机制来释放一些无用的对象,以腾出足够的空间来分配新对象。
垃圾回收的具体策略和算法在不同的jvm实现中可能会有所不同,但其核心目标都是为了确保堆内存的可用空间。
·初始化零值:在内存分配完成后,jvm会对对象的内存空间进行初始化。对于基本数据类型,jvm会将其初始化为零值。例如整形会被初始化为零,浮点型会被初始化为零点零,偶尔型会被初始化为false,引用类型会被初始化为now。这样做的目的是为了确保对象的属性在使用之前都有一个明确的初始值,避免了因为为初始化而导致的程序错误。
在初始化零值的过程中,jvm会根据对象的类型和属性来逐个初始化对象的各个属性值。如果属性是基本数据类型,那么它的初始值就是对应数据类型的零值。如果属性是引用类型,那么它的初始值就是no。通过这样的初始化过程,可以确保对象的各个属性都处于一个可控的状态,为后续的操作打下了良好的基础。
·设置对象头:在内存分配和初始化零值完成后,jvm会在内存中为对象设置对象头。对象头、是对象在内存中的标识符,包含了一些必要的信息,例如对象的类型信息、gc相关信息等。
→首先对象头会包含对象的类型信息,这个信息是在加载的时候确定的,它只是了对象所属的类的类型。这样jvm在操作对象的时候可以根据对象头中的类型信息来准确的调用对象的方法和属性。
→其次对象头还包含了gc相关的信息,比如对象的引用技术、对象的分带信息等。这些信息对于jvm的垃圾回收机制非常重要,它们能够帮助jvm正确的管理内存,及时回收不再使用的对象,从而避免内存泄露和内存溢出的问题。
→除此之外对象头还可能包含一些额外的信息,比如对象的哈希码、对象的年龄等。这些信息虽然不是必须的,但它们可以为对象提供额外的功能和特性。例如在多线程环境下所状态信息可以帮助jvm实现线程同步执行innate方法。
→最后一步是执行对象的innate方法。在java中每个类都有一个与之对应的构造方法,在对象创建的时候jvm会调用该构造方法来初始化对象,这个过程就是执行innate方法。
innate方法的主要作用是完成对象的初始化工作,包括对对象的属性进行复制,调用其他方法进行一些初始化操作等。在执行in its方法之前,jvm会先为对象分配内存,初始化零值,设置对象头等操作,确保对象处于一个合法且可用的状态。
在执行innate方法的过程中,可以在构造方法中编写一些初始化逻辑,比如对对象的属性进行初始化复制,调用其他方法进行初始化操作等。这样当使用new关键字创建对象的时候,jvm就会按照定义的初始化逻辑来初始化对象,确保对象在创建之后处于一个正确的状态。
通过以上五个步骤,jvm成功创建了一个对象。当使用new关键字创建一个对象的时候,其实就是在触发了jvm的创建对象的过程。了解这个过程不仅可以帮助更好的理解java程序的执行流程,还能够在技术面试中秀出技术功底。
希望通过今天的分享,大家对jvm创建对象的过程有了更深入的了解。