背景:我们在通过写代码创建一个对象时,有时会秃然想到,在创建一个对象时做了哪些事情?怎么来的这个对象?那么我们今天来了解一下创建对象的背后都发生了啥。在那之前:
一、对象创建过程
首先我们通过一张图与一段代码来大概了解创建一个对象的步骤。
- New类名 。》 图中为New String(),指定创建的对象为String
- 根据new的参数在常景池中定位一个类符号的引用。》图中创建了String对象,固会去找当前对象Class。
- 如果没有找到这个符号的引用,说明类还没有被加载,则进行类的加载,解析和初始化。》图中为加载当前对象Class。
- 虚拟机为对象分配内存(位于堆中)。》为当前String对象在堆中开辟空间。原理参考下文JVM如何为对象开辟空间。
- 分配的内存初始化为零值(不包括对象头)。》如果是int那么为0,String则为"",对值的初始化。
- 调用对象的<init>方法。》图中为执行String的构造方法
本次调用的String构造方法源码:
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
创建过程原理示例代码:
String str = new String("Hello World");
创建过程原理图:
那么经历以上步骤,我们的String对象就创建完成了,是不是很简单呢?
二、JVM如何为对象开辟空间
首先使用哪种算法,跟垃圾回收机制有关。
标记整理和标记压缩是指针碰撞的回收算法。指针回收会使用。
标记清除为空间列表。 创建一般使用该算法。
当然垃圾回收机制影响算法的概念,相当于做了垃圾分类的城市,你在处理垃圾的时候就要把垃圾分类再丢,如果没有做垃圾分类的城市,那么你可以直接全部丢一个袋子扔掉。这时候就是不同城市的垃圾回收机制影响你的处理垃圾的思想分类行为,同理就是垃圾回收机制影响程序的算法原理。
2.1、指针碰撞
首先Cas实现同步是在CPU层面加锁。硬件层面加锁。效率高。
原理实际上会在放入的时候调用C语言的CAS方法。Unsafe类中的compareAndSwapObject方法
这里案例的意思就是内存被obj1和obj2占用后,剩下的空间只能存放一个对象,那么如果此时多线程创建obj3和obj4,同时去抢,那么总有一个资源会抢到。当然如果说非得创建两个就会出现内存溢出的问题。
内存溢出参考:https://blog.csdn.net/qq_43227967/article/details/106054100
2.2、空闲列表
空闲列表存放的原则:哪块区域空闲,就会存放在哪块区域
当然如果是多线程,那么其实是有一个线程缓存区的概念,会有一块一块的区域,每一个线程对应一块区域,如果A线程满了,那么就会通过CAS机制去抢占线程B的区域。来避免同时抢占一个位置的情况。
三、总结
Java创建对象首先是new 类名,那么实现会根据new的参数在常量池中定义一个对该类符号的引用,如果没有找到这个符号的引用,说明这个类没有被加载,那么进行类的加载、解析、初始化。然后虚拟机为其分配内存(位于堆中)使用指针碰撞或者是空闲列表,与垃圾算法相关联,默认初始值为零。最后调用对象的init方法。完成创建。